Skip to Content

AI API

POST /v1/ai/process matches a contextual ad to one assistant message. The AI SDK integrations call this endpoint, and you can call it directly.

POST /v1/ai/process

POST https://api.adzen.ai/v1/ai/process

Headers

HeaderRequiredValue
X-API-KeyOne of X-API-Key or AuthorizationYour AI API key
AuthorizationOne of X-API-Key or AuthorizationBearer <key>. If you send both headers, Adzen uses X-API-Key.
Content-TypeYesapplication/json
Idempotency-KeyNoA unique string for this request. Send the same value on every retry of it. Publisher insights counts requests that share a value once. See Idempotency and retries.

See Authentication for how to get a key.

Body

FieldTypeRequiredRules
message_idstringYesYour id for this assistant message. Must not be empty. Use a new value for each assistant message: a reused message_id can make a later message’s beacons count as duplicates.
contentstringYesThe text to match an ad to. Must not be empty. At most 10,000 bytes of UTF-8, not characters.
locationstringYes, to receive an adThe viewer’s US state as an uppercase ISO 3166-2 code, such as US-CA. A request without location, or with a value that does not start with US-, returns empty ads.
conversation_idstringNoYour id for the conversation. Adzen adds it to the impression beacon URLs.
promptstringNoThe user prompt that produced content.
content_rolestringNoWho wrote content: user or assistant. Case-insensitive. Other values are ignored.

Adzen checks the API key first, then parses the body, then checks the field rules above.

Example request

curl -X POST https://api.adzen.ai/v1/ai/process \ -H 'X-API-Key: YOUR_API_KEY' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: 0f8b6d2e-5c1a-4e7b-9d3f-2a6c8e1b4f70' \ -d '{ "message_id": "msg_abc123", "content": "For a leaking pipe, shut off the main water valve first, then call a plumber.", "conversation_id": "conv_7f3a9b2e", "location": "US-WA" }'

Response

A match returns 200 with one ad:

{ "message_id": "msg_abc123", "ads": [ { "ad_id": 1071, "title": "24/7 Emergency Plumbing", "cta": "Book a licensed plumber", "click_through_url": "https://api.adzen.ai/dea/ai/redirect/k3x9q2m", "advertiser_name": "Example Plumbing Co.", "sponsor_logo_url": "https://cdn.example.com/logos/example-plumbing.png", "creative_url": "https://cdn.example.com/creatives/plumber-van.jpg", "description": "Same-day repairs for leaks, clogs and burst pipes.", "pricing_model": "CPC", "relevancy_score": 0.9473, "placement": "after_message", "pixel_trackers": [], "render_impression_url": "https://api.adzen.ai/dea/ai/impressions/render?ad_id=1071&message_id=msg_abc123&slug=k3x9q2m&conversation_id=conv_7f3a9b2e&ad_unit_position=after_message&timestamp=2026-10-30T14%3A02%3A11.483920517%2B00%3A00", "view_impression_url": "https://api.adzen.ai/dea/ai/impressions/view?ad_id=1071&message_id=msg_abc123&slug=k3x9q2m&conversation_id=conv_7f3a9b2e&ad_unit_position=after_message&timestamp=2026-10-30T14%3A02%3A11.483920517%2B00%3A00&viewability_ms=1000" } ] }

No match also returns 200, with an empty ads array:

{ "message_id": "msg_abc123", "ads": [] }
FieldTypeMeaning
message_idstringThe message_id you sent.
adsarrayAt most one ad. Empty when no ad is returned for this message.

Each object in ads has these fields. Fields typed string or null are sent as null when they have no value; no field is left out.

FieldTypeMeaning
ad_idintegerAdzen’s id for the ad.
titlestringThe ad headline.
ctastringThe call-to-action text.
click_through_urlstringThe URL the ad links to. See Click URL.
advertiser_namestringThe advertiser’s name, to show as the sponsor.
sponsor_logo_urlstringURL of the advertiser’s logo. Can be an empty string.
creative_urlstring or nullURL of the ad image.
descriptionstring or nullBody text for the ad.
pricing_modelstringHow the advertiser pays for this ad: CPC or CPM.
relevancy_scorenumberHow closely the ad matches content, from 0 to 1. Higher is closer.
placementstringafter_message: show the ad below the assistant message named by message_id.
pixel_trackersarrayReserved. An empty array. Impressions are counted through render_impression_url and view_impression_url.
render_impression_urlstringBeacon to fire when the ad is shown. See Impression beacons.
view_impression_urlstringBeacon to fire when the ad is viewed. See Impression beacons.

Errors

Errors from this endpoint have this body:

{ "error": "content must not be empty" }

Malformed JSON (400), a wrong Content-Type (415) and a body that does not fit the schema (422) return a plain-text body instead.

StatusBodyWhenRetry?
400{"error": "message_id must not be empty"}message_id is an empty stringNo
400{"error": "content must not be empty"}content is an empty stringNo
400{"error": "content must not exceed 10000 characters"}content is over 10,000 bytesNo
400Plain textThe body is not valid JSONNo
401{"error": "missing profile id"}The API key is missing or is not an AI API keyNo. Check the key.
401{"error": "unknown profile"}The key’s account is not set up for the AI API. Contact your Adzen account representative.No
403{"error": "publisher profile is disabled"}Your account is disabledNo
403Not JSONThe request came from an IP address outside the USNo
415Plain textContent-Type is missing or is not application/jsonNo
422Plain textmessage_id or content is missing, or a field has the wrong typeNo
429{"error": "endpoint overloaded, retry shortly"}Adzen is at capacity for the moment. The response has Retry-After: 1.Yes, after Retry-After seconds
500 to 599VariesA server or gateway errorYes, with backoff

No fill is not an error. It returns 200 with "ads": []. See Rate limits for limits across products.

Click URL

Link the ad to click_through_url exactly as returned. The URL has the form https://api.adzen.ai/dea/ai/redirect/<slug> and answers 302 with the advertiser’s landing page. Adzen counts a click only when the viewer goes through this URL.

Impression beacons

Each ad carries two beacon URLs. Fire each one once, from the viewer’s browser, exactly as returned.

BeaconFire it when
render_impression_urlThe ad is shown in the conversation.
view_impression_urlThe ad has been 100% visible for one continuous second.

The view URL already carries viewability_ms=1000. Do not change it.

  • Beacons are GET requests. A beacon returns 204 No Content.
  • A beacon with ad_id or message_id removed, or a view beacon without an integer viewability_ms, returns 400 with {"error": "..."}.
  • Adzen counts one beacon of each type per message_id and ad_id pair for the same IP address and user agent. A repeat within 5 minutes still returns 204 and counts as invalid.
  • Beacon and click URLs return 403 to requests from IP addresses outside the US.

Fire beacons from the viewer’s browser. Adzen validates each beacon against the viewer’s IP address and user agent.

Idempotency and retries

Send the same Idempotency-Key on every retry of a request. Publisher insights counts requests that share an Idempotency-Key once in ad_requests. Each request sent without the header counts as a separate request.

Each retry returns a fresh match. It can return a different ad, or none.

Retry 429 after the Retry-After delay and 5xx with backoff. Do not retry 400, 401, 403, 415 or 422 without changing the request.

Timing

Matching has a deadline of 2.5 seconds. A request that takes longer returns 200 with empty ads.

Last updated on