Skip to main content

Overview

This tutorial covers everything you need to integrate with Kaireon’s two core APIs:
  • Recommend API — Get personalized offer recommendations for a customer
  • Respond API — Record customer interactions (impressions, clicks, conversions)

Prerequisites

Before starting, ensure you have:
  • A running Kaireon instance (local or https://playground.kaireonai.com)
  • At least one active decision flow with offers, channels, and creatives configured
  • Your tenant ID (found in Settings > General)
  • An API key (generated in Settings > API Keys)

Authentication

All API requests require two headers:
HeaderDescription
x-tenant-idYour tenant identifier
x-api-keyYour API key (hashed with HMAC-SHA256 on the server)
curl -H "x-tenant-id: your-tenant-id" \
     -H "x-api-key: your-api-key" \
     https://your-instance.com/api/v1/recommend
API keys are hashed on the server using HMAC-SHA256 with the API_KEY_PEPPER environment variable. Store your API key securely — it cannot be retrieved after creation.

Base URL

EnvironmentBase URL
Local developmenthttp://localhost:3000/api/v1
Playgroundhttps://playground.kaireonai.com/api/v1
ProductionYour custom domain + /api/v1

Recommend API

The Recommend API is the primary decisioning endpoint. It executes a decision flow for a specific customer and returns ranked, personalized offers.

Endpoint

POST /api/v1/recommend

Request Body

{
  "customerId": "cust_12345",
  "channelId": "ch_email",
  "decisionFlowId": "df_credit_cards",
  "maxOffers": 3,
  "placement": "hero_offer",
  "attributes": {
    "tier": "gold",
    "source": "campaign_q1",
    "device": "mobile"
  },
  "trace": true
}
FieldTypeRequiredDescription
customerIdstringYesThe customer to generate recommendations for
channelIdstringYesDelivery channel (determines which creatives are selected)
decisionFlowIdstringNoSpecific flow to execute (uses default flow if omitted)
maxOffersnumberNoMaximum offers to return (default: 5)
placementstringNoNamed placement slot within the channel
attributesobjectNoRequest-time attributes available as attributes.* in formulas
tracebooleanNoIf true, returns a decision trace ID for debugging

Response

{
  "customerId": "cust_12345",
  "recommendations": [
    {
      "offerId": "act_platinum_cc",
      "offerName": "Platinum Rewards Card",
      "categoryId": "cat_credit_cards",
      "rank": 1,
      "score": 0.89,
      "channelId": "ch_email",
      "creativeId": "treat_platinum_email",
      "content": {
        "subject": "You're invited, Sarah - Earn 3x Rewards",
        "headline": "Platinum Rewards Card",
        "body": "Start earning 3x points with a personalized rate of 17.49% APR.",
        "ctaText": "Apply Now",
        "ctaUrl": "https://example.com/apply/platinum"
      },
      "personalization": {
        "personalized_rate": 17.49,
        "annual_fee_waiver": true
      }
    },
    {
      "offerId": "act_cashback",
      "offerName": "Cash Back Card",
      "rank": 2,
      "score": 0.74,
      "channelId": "ch_email",
      "creativeId": "treat_cashback_email",
      "content": {
        "subject": "Sarah, get 2% cash back on everything",
        "headline": "Cash Back Card",
        "body": "No annual fee, 2% cash back on all purchases.",
        "ctaText": "Learn More",
        "ctaUrl": "https://example.com/apply/cashback"
      },
      "personalization": {
        "personalized_rate": 18.24
      }
    }
  ],
  "decisionFlowId": "df_credit_cards",
  "traceId": "trace_abc123",
  "processedAt": "2026-03-10T14:30:00Z"
}

Response Fields

FieldDescription
recommendations[]Ordered array of recommended offers (highest score first)
recommendations[].scoreFinal composite score after arbitration
recommendations[].contentRendered creative content with personalization variables resolved
recommendations[].personalizationComputed values from the Compute stage
traceIdDecision trace ID (only when trace: true in request)

Respond API

The Respond API records customer interactions with recommendations. This data feeds back into behavioral metrics, contact policies, and experiment analysis.

Endpoint

POST /api/v1/respond

Request Body

{
  "customerId": "cust_12345",
  "offerId": "act_platinum_cc",
  "channelId": "ch_email",
  "outcomeType": "click",
  "creativeId": "treat_platinum_email",
  "traceId": "trace_abc123",
  "metadata": {
    "clickPosition": "hero_banner",
    "deviceType": "mobile"
  }
}
FieldTypeRequiredDescription
customerIdstringYesThe customer who interacted
offerIdstringYesThe offer they interacted with
channelIdstringYesThe channel the interaction occurred on
outcomeTypestringYesThe type of interaction (see Outcome Types)
creativeIdstringNoThe specific creative/treatment shown
traceIdstringNoLinks this interaction back to the original recommendation
metadataobjectNoArbitrary key-value data attached to the interaction

Response

{
  "id": "int_xyz789",
  "customerId": "cust_12345",
  "offerId": "act_platinum_cc",
  "channelId": "ch_email",
  "outcomeType": "click",
  "creativeId": "treat_platinum_email",
  "traceId": "trace_abc123",
  "recordedAt": "2026-03-10T15:45:00Z"
}

Common Outcome Types

TypeWhen to Record
impressionCustomer was shown the recommendation
clickCustomer clicked/tapped the recommendation
conversionCustomer completed the desired action (purchase, application, etc.)
dismissCustomer explicitly dismissed the recommendation
not_interestedCustomer indicated disinterest
opt_outCustomer opted out of this type of communication

Advanced Topics

Decision Traces

When you set trace: true in the Recommend request, Kaireon records a forensic trace of the entire decision process. Retrieve it with:
GET /api/v1/decision-traces/:traceId
Trace response:
{
  "traceId": "trace_abc123",
  "customerId": "cust_12345",
  "decisionFlowId": "df_credit_cards",
  "stages": [
    {
      "name": "enrich",
      "duration": 12,
      "input": { "customerId": "cust_12345" },
      "output": { "customer.loyalty_score": 85, "customer.credit_score": 720 }
    },
    {
      "name": "compute",
      "duration": 3,
      "computed": {
        "act_platinum_cc": { "personalized_rate": 17.49 },
        "act_cashback": { "personalized_rate": 18.24 }
      }
    },
    {
      "name": "filter",
      "duration": 5,
      "candidatesIn": 15,
      "candidatesOut": 8,
      "filtered": ["act_home_loan (segment_required)", "act_auto_loan (propensity < 0.4)"]
    },
    {
      "name": "score",
      "duration": 8,
      "scores": {
        "act_platinum_cc": 0.89,
        "act_cashback": 0.74
      }
    },
    {
      "name": "rank",
      "duration": 2,
      "finalOrder": ["act_platinum_cc", "act_cashback"]
    }
  ],
  "totalDuration": 30,
  "processedAt": "2026-03-10T14:30:00Z"
}
Decision traces are invaluable for debugging why a specific offer was or was not recommended. Enable tracing in staging environments and at a sample rate in production (configurable in Settings > Tracing).

Experiments

When an A/B experiment is active, the Recommend API automatically assigns customers to control or variant groups based on creative weights. The response includes experiment metadata:
{
  "recommendations": [
    {
      "offerId": "act_platinum_cc",
      "creativeId": "treat_platinum_email_variant_a",
      "experiment": {
        "experimentId": "exp_cc_cta_test",
        "variant": "variant_a",
        "weight": 30
      }
    }
  ]
}
Track experiment results in Algorithms > Experiments, where Kaireon calculates:
  • Conversion rate per variant
  • Uplift (percentage improvement over control)
  • Statistical significance (z-test)
  • Confidence interval

Computed Values in Responses

The personalization field in each recommendation contains the evaluated computed values from the decision flow’s Compute stage. These values are calculated per customer using:
  • Offer custom fieldsbase_rate, annual_fee, etc.
  • Enriched customer datacustomer.loyalty_score, customer.credit_score
  • Request-time attributesattributes.tier, attributes.device
{
  "personalization": {
    "personalized_rate": 17.49,
    "annual_fee_waiver": true,
    "bonus_points": 5000
  }
}
See Computed Values for formula syntax and configuration details.

Error Handling

Common Error Responses

StatusCodeDescription
400VALIDATION_ERRORInvalid request body (missing required fields, wrong types)
401UNAUTHORIZEDMissing or invalid API key
403FORBIDDENTenant does not have access to the requested resource
404NOT_FOUNDDecision flow, customer, or offer not found
429QUOTA_EXCEEDEDMonthly decision quota reached (see Licensing)
500INTERNAL_ERRORServer error — contact support
Error response format:
{
  "error": "Validation failed",
  "code": "VALIDATION_ERROR",
  "details": [
    { "field": "customerId", "message": "customerId is required" }
  ]
}

Rate Limiting

Kaireon applies a sliding-window rate limit to protect the platform:
TierRate Limit
Community100 requests/minute
Professional1,000 requests/minute
EnterpriseCustom (configurable)
When rate-limited, the API returns:
HTTP 429 Too Many Requests
Retry-After: 12
Rate limits apply per tenant, not per API key. Multiple API keys for the same tenant share the same rate limit window.

What’s Next?