Skip to main content

POST /api/v1/respond

Records the outcome of a recommendation delivered via the Recommend API. Outcomes feed into behavioral metrics, adaptive model training, experiment analysis, and attribution.

Request Body

{
  "customerId": "CUST001",
  "creativeId": "creative_001",
  "outcome": "click",
  "idempotencyKey": "click-cust001-offer001-1710590400",
  "interactionId": "550e8400-e29b-41d4-a716-446655440000",
  "offerId": "offer_001",
  "channelId": "channel_email",
  "placementId": "placement_hero",
  "rank": 1,
  "context": {
    "source": "email_campaign_q1",
    "utm_medium": "email"
  },
  "outcomeDetails": {
    "product_sku": "SKU-12345"
  },
  "timestamp": "2026-03-16T14:35:00.000Z",
  "conversionValue": 149.99,
  "attributes": {
    "device": "mobile",
    "browser": "safari"
  }
}

Field Reference

FieldTypeRequiredDescription
customerIdstringYesThe customer who interacted with the recommendation
creativeIdstringYes*The Creative that was shown. Alias: treatmentId (deprecated)
outcomestringYes*The outcome type key (e.g., "impression", "click", "convert", "dismiss"). Must match a registered Outcome Type. Alias: interactionType
idempotencyKeystringYesUnique key to prevent double-counting. Can also be sent as the Idempotency-Key HTTP header
interactionIdstringNoThe interactionId returned by the Recommend API, used to link the outcome to the original decision
offerIdstringNoOffer ID. If omitted, resolved automatically from the creative’s parent offer
channelIdstringNoChannel ID. If omitted, resolved from the creative
placementIdstringNoPlacement ID. If omitted, resolved from the creative
rankintegerNoThe position at which the offer was displayed (1-indexed)
contextobjectNoArbitrary context metadata (campaign source, UTM params, etc.)
outcomeDetailsobjectNoStructured details about the outcome (e.g., product SKU, plan selected)
timestampstringNoISO 8601 timestamp of the interaction. Defaults to the current server time
conversionValuenumberNoMonetary value of the conversion (used for attribution and revenue reporting)
attributesobjectNoAdditional attributes (device, browser, etc.). Used for online model learning
channelstringNoChannel name string (stored in context)
placementstringNoPlacement name string (stored in context)
responseTimenumberNoTime in milliseconds the customer took to respond
deviceTypestringNoDevice type string (stored in context)
Fields marked Yes* require at least one of the aliased pair. You must provide either creativeId or treatmentId, and either outcome or interactionType.

Idempotency

Every call to the Respond API requires an idempotency key to prevent duplicate outcome recording. You can provide it in two ways:
  1. Request body: "idempotencyKey": "unique-key-here"
  2. HTTP header: Idempotency-Key: unique-key-here
If both are provided, the body value takes precedence. When a duplicate key is detected, the API returns the original record with "status": "already_recorded" and a 200 status code (not 201).

Response: New Record (201)

{
  "id": "ih_abc123",
  "interactionId": "550e8400-e29b-41d4-a716-446655440000",
  "offerId": "offer_001",
  "outcomeType": "click",
  "classification": "positive",
  "status": "recorded",
  "timestamp": "2026-03-16T14:35:00.000Z"
}

Response: Duplicate (200)

When the same idempotencyKey is sent again:
{
  "id": "ih_abc123",
  "interactionId": "550e8400-e29b-41d4-a716-446655440000",
  "offerId": "offer_001",
  "outcomeType": "click",
  "status": "already_recorded",
  "timestamp": "2026-03-16T14:35:00.000Z"
}

Outcome Types

Outcomes must be registered in the platform before they can be recorded. Each outcome type has a classification that drives downstream behavior:
ClassificationEffectExamples
positiveIncrements positive counters, triggers attribution, updates adaptive models with rewardclick, accept, convert, purchase
negativeIncrements negative counters, updates models with penaltydismiss, not_interested, unsubscribe
neutralTracked but does not affect scoringimpression, view, requested_info
Register outcome types in Studio > Outcome Types or via POST /api/v1/outcome-types.

Examples

Record an Impression

curl -X POST https://playground.kaireonai.com/api/v1/respond \
  -H "Content-Type: application/json" \
  -H "X-Tenant-Id: my-tenant" \
  -H "Authorization: Bearer sk_live_abc123" \
  -d '{
    "customerId": "CUST001",
    "creativeId": "creative_001",
    "outcome": "impression",
    "idempotencyKey": "imp-cust001-creative001-20260316-1430",
    "interactionId": "550e8400-e29b-41d4-a716-446655440000",
    "rank": 1
  }'

Record a Click

curl -X POST https://playground.kaireonai.com/api/v1/respond \
  -H "Content-Type: application/json" \
  -H "X-Tenant-Id: my-tenant" \
  -H "Authorization: Bearer sk_live_abc123" \
  -d '{
    "customerId": "CUST001",
    "creativeId": "creative_001",
    "outcome": "click",
    "idempotencyKey": "click-cust001-creative001-20260316-1435",
    "interactionId": "550e8400-e29b-41d4-a716-446655440000",
    "context": {
      "source": "email_hero_banner"
    }
  }'

Record a Conversion with Value

curl -X POST https://playground.kaireonai.com/api/v1/respond \
  -H "Content-Type: application/json" \
  -H "X-Tenant-Id: my-tenant" \
  -H "Authorization: Bearer sk_live_abc123" \
  -d '{
    "customerId": "CUST001",
    "creativeId": "creative_001",
    "outcome": "convert",
    "idempotencyKey": "conv-cust001-offer001-20260316",
    "interactionId": "550e8400-e29b-41d4-a716-446655440000",
    "offerId": "offer_001",
    "conversionValue": 299.99,
    "outcomeDetails": {
      "plan": "platinum",
      "term_months": 12
    }
  }'

Error Responses

StatusCause
400Missing required fields (customerId, creativeId/treatmentId, outcome/interactionType, idempotencyKey), unknown outcome type, or invalid JSON
401Missing or invalid X-Tenant-Id / API key
404Creative not found or belongs to another tenant
415Content-Type header is not application/json
429Rate limit exceeded (1,000 requests per 60s per tenant)
500Internal server error
Example error (unknown outcome type):
{
  "error": {
    "code": "BAD_REQUEST",
    "message": "Unknown outcome type: \"purchased\". Register it in Outcome Types first.",
    "status": 400,
    "traceId": "d4e5f678-90ab-cdef-1234-567890abcdef",
    "timestamp": "2026-03-16T14:35:00.000Z"
  }
}
See also: Outcome Types | Behavioral Metrics | API Tutorial