Skip to main content

API Integration Guide

Make real-time predictions with your adaptive learning loops using our REST API. Loops continuously improve with each prediction and training example.

Overview

Heimdall Loop provides three main API endpoints:

  1. Create Loop Definition - Define your loop structure
  2. Train Loop - Provide training data to improve your model
  3. Predict - Make predictions and get feature contributions

Base URL

All Loop API endpoints are available at:

https://loop.heimdallapp.org

Authentication

All endpoints require authentication via headers:

  • X-api-key - Your API key (generated from the loop detail page)
  • X-username - Your Heimdall username
  • x-loop-id - Your Loop ID (found on the loop detail page)
Getting Your Credentials
  1. Navigate to your loop page in the Heimdall dashboard
  2. Click "Generate API Key" at the top of the page
  3. Find your Loop ID on the loop detail page
  4. Use your Heimdall username for authentication

1. Create Loop Definition

Define your adaptive learning loop structure.

POST /definitions/

Request Body

{
"name": "Customer Recommendation Loop",
"task_type": "classification",
"input_schema": {
"user_id": "string",
"item_id": "string",
"rating": "integer",
"time_of_day": "integer"
},
"output_schema": {
"recommendation": "string"
}
}

Request Fields

  • name (string, required) - Descriptive name for your loop
  • task_type (string, required) - Either "classification" or "regression"
  • input_schema (object, required) - Dictionary mapping field names to types
    • Supported types: string, integer, float, boolean, array, object
  • output_schema (object, required) - Dictionary with exactly one field
    • Must contain exactly one field name and type

Response

{
"definition_id": "507f1f77bcf86cd799439011",
"name": "Customer Recommendation Loop",
"task_type": "classification",
"input_schema": {
"user_id": "string",
"item_id": "string",
"rating": "integer",
"time_of_day": "integer"
},
"output_schema": {
"recommendation": "string"
},
"model_url": "s3://bucket/model.pkl",
"created_at": "2024-01-01T00:00:00"
}

2. Train Loop

Provide training data to improve your loop model. You can train with single examples or batches.

POST /train/

Request Headers

  • X-api-key - Your API key
  • X-username - Your username
  • x-loop-id - Your Loop ID

Request Body

Single Training Example:

{
"data": {
"user_id": "user_123",
"item_id": "item_456",
"rating": 5,
"time_of_day": 14,
"recommendation": "highly_recommended"
}
}

Batch Training (Multiple Examples):

{
"data": [
{
"user_id": "user_123",
"item_id": "item_456",
"rating": 5,
"time_of_day": 14,
"recommendation": "highly_recommended"
},
{
"user_id": "user_124",
"item_id": "item_789",
"rating": 2,
"time_of_day": 22,
"recommendation": "not_recommended"
}
]
}

Response

{
"status": "success",
"message": "Successfully trained 2 sample(s)",
"trained_samples": 2,
"failed_samples": 0,
"errors": []
}

3. Make Predictions

Make predictions and get feature contributions for explainability.

POST /predict/

Request Headers

  • X-api-key - Your API key
  • X-username - Your username
  • x-loop-id - Your Loop ID

Request Body

Single Prediction:

{
"data": {
"user_id": "user_123",
"item_id": "item_456",
"rating": 4,
"time_of_day": 15
}
}

Batch Predictions:

{
"data": [
{
"user_id": "user_123",
"item_id": "item_456",
"rating": 4,
"time_of_day": 15
},
{
"user_id": "user_125",
"item_id": "item_999",
"rating": 3,
"time_of_day": 20
}
]
}

Response

{
"status": "success",
"message": "Successfully predicted 2 sample(s)",
"predictions": [
{
"recommendation": "recommended",
"explanation": {
"top_contributors": [
{
"feature": "rating",
"contribution": 0.42,
"weight": 1.2,
"value": 4.0
},
{
"feature": "time_of_day",
"contribution": 0.28,
"weight": 0.8,
"value": 15.0
},
{
"feature": "user_id",
"contribution": 0.15,
"weight": 0.5,
"value": 0.0
}
]
}
},
{
"recommendation": "not_recommended",
"explanation": {
"top_contributors": [
{
"feature": "rating",
"contribution": -0.35,
"weight": 1.2,
"value": 3.0
},
{
"feature": "time_of_day",
"contribution": -0.22,
"weight": 0.8,
"value": 20.0
}
]
}
}
],
"failed_samples": 0,
"errors": []
}

Understanding Feature Contributions

Each prediction includes an explanation object with top_contributors showing:

  • feature - The input field name
  • contribution - How much this feature contributed to the prediction (positive or negative)
  • weight - The model's learned weight for this feature
  • value - The actual value of this feature in the input

This helps you understand which factors most impact each prediction.

Complete Python Example

import requests

# Configuration
API_KEY = 'YOUR_API_KEY'
USERNAME = 'YOUR_USERNAME'
LOOP_ID = 'YOUR_LOOP_ID'
BASE_URL = 'https://loop.heimdallapp.org'

headers = {
'X-api-key': API_KEY,
'X-username': USERNAME,
'x-loop-id': LOOP_ID,
'Content-Type': 'application/json'
}

# Make a prediction
prediction_data = {
"data": {
"user_id": "user_123",
"item_id": "item_456",
"rating": 4,
"time_of_day": 15
}
}

response = requests.post(
f'{BASE_URL}/predict/',
headers=headers,
json=prediction_data
)

if response.status_code == 200:
result = response.json()
prediction = result['predictions'][0]

# Get the predicted value
output_field = list(prediction.keys())[0] # Get the output field name
predicted_value = prediction[output_field]

print(f"Prediction: {predicted_value}")

# Get feature contributions
if 'explanation' in prediction:
print("\nTop Contributing Features:")
for contributor in prediction['explanation']['top_contributors']:
print(f" {contributor['feature']}: {contributor['contribution']:+.2f} "
f"(weight: {contributor['weight']:.2f}, value: {contributor['value']})")
else:
print(f"Error: {response.status_code}")
print(response.text)

Continuous Learning Workflow

Here's a complete example showing the continuous learning cycle:

import requests

API_KEY = 'YOUR_API_KEY'
USERNAME = 'YOUR_USERNAME'
LOOP_ID = 'YOUR_LOOP_ID'
BASE_URL = 'https://loop.heimdallapp.org'

headers = {
'X-api-key': API_KEY,
'X-username': USERNAME,
'x-loop-id': LOOP_ID,
'Content-Type': 'application/json'
}

# 1. Make a prediction
prediction_response = requests.post(
f'{BASE_URL}/predict/',
headers=headers,
json={
"data": {
"user_id": "user_123",
"item_id": "item_456",
"rating": 4,
"time_of_day": 15
}
}
)

prediction = prediction_response.json()['predictions'][0]
predicted_recommendation = prediction['recommendation']

# 2. Use the prediction in your application
print(f"Showing recommendation: {predicted_recommendation}")

# 3. When you get user feedback (ground truth), feed it back as training data
# For example, if the user actually clicked/interacted:
actual_outcome = "highly_recommended" # Ground truth from user behavior

training_data = {
"data": {
"user_id": "user_123",
"item_id": "item_456",
"rating": 4,
"time_of_day": 15,
"recommendation": actual_outcome # Include the actual outcome
}
}

# 4. Train the model with the feedback
train_response = requests.post(
f'{BASE_URL}/train/',
headers=headers,
json=training_data
)

print(f"Model updated: {train_response.json()['message']}")

Error Handling

Common Error Codes

  • 400 Bad Request - Invalid request format or missing required fields
  • 401 Unauthorized - Invalid API key, username, or Loop ID
  • 422 Unprocessable Entity - Invalid data types or schema mismatch
  • 500 Internal Server Error - Server-side error

Error Response Format

{
"status": "failed",
"message": "Error message describing what went wrong",
"errors": [
"Detailed error message 1",
"Detailed error message 2"
]
}

Best Practices

  • Always check response status codes
  • Implement retry logic for transient errors (5xx)
  • Validate data types match your schema before sending
  • Cache API keys securely (never commit to version control)
  • Monitor API usage and rate limits
  • Handle partial failures in batch requests (check failed_samples)

Rate Limits

Loops are designed for high-volume usage. Contact support if you need information about specific rate limits for your use case.

Next Steps