Conversions
A conversion is reported on the click that earned it, keyed on the az_cid
from the landing URL. It shows up in insights
against that click’s campaign and ad.
POST /conversions
POST https://api.adzen.ai/v1/ad-manager/conversionsHeaders
| Header | Required | Value |
|---|---|---|
Authorization | Yes, unless you send X-API-Key | Bearer YOUR_API_KEY. You can send X-API-Key: YOUR_API_KEY instead. If both are sent, X-API-Key is used. |
Content-Type | Yes | application/json |
Idempotency-Key | No | See Idempotency. Without it, a resent conversion still counts once: see Deduplication. |
Use the organization key or an advertiser key. An advertiser key attributes conversions only to clicks on its own ad account’s campaigns.
Body
The body is {"data": [...]}, an array of 1 to 1,000 events. Any other
top-level key returns 400 invalid_value, with param naming the key.
| Field | Type | Required | Rules |
|---|---|---|---|
click_id | string | Yes | The az_cid value from the landing URL. 1 to 255 characters after trimming, no control characters. Matched without regard to case. |
event_name | string | Yes | lead, purchase, sign_up, add_to_cart or other. |
event_time | integer | Yes | When the conversion happened, in Unix seconds. A JSON integer greater than 0. At most 300 seconds ahead of Adzen’s clock. Must fall between the click time and the end of the campaign’s attribution window, both included. |
dedupe_key | string | Yes | Your id for this conversion. 1 to 255 characters after trimming, no control characters. |
value_micros | integer | No | The conversion value in USD micros. 0 to 1,000,000,000,000,000. null is the same as leaving it out. |
currency | string | No | Exactly USD. Required when value_micros is set. |
click_id, event_name and dedupe_key are trimmed before they are checked.
currency must be exactly USD. Any other key in an event fails that event
with invalid_value.
Example request
curl -X POST https://api.adzen.ai/v1/ad-manager/conversions \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"data": [
{
"click_id": "8f3a91d2e7b44c06a1b2c3d4e5f60718",
"event_name": "purchase",
"event_time": 1793640000,
"dedupe_key": "order-551203",
"value_micros": 35000000,
"currency": "USD"
},
{
"click_id": "dc881f6cf54944b8b5eb86419a76d878",
"event_name": "lead",
"event_time": 1793641200,
"dedupe_key": "lead-88412"
}
]
}'Response
Each event is checked on its own. Valid events are stored even when others in
the batch fail. The call returns 200 whenever the batch itself is readable,
even if every event failed.
{
"object": "conversion_batch",
"received": 2,
"accepted": 1,
"errors": [
{
"index": 1,
"code": "unknown_click",
"message": "No click with this click_id in your organization."
}
]
}| Field | Type | Description |
|---|---|---|
object | string | Always conversion_batch. |
received | integer | The number of events in data. |
accepted | integer | Events that passed every check, including resends of conversions already stored and conversions on invalid clicks. |
errors | array | One entry per failed event, sorted by index. Empty when every event was accepted. |
errors[].index | integer | The event’s zero-based position in data. |
errors[].code | string | invalid_value, unknown_click or outside_window. |
errors[].message | string | What failed, naming the field for invalid_value. |
Event errors
code | When | Retry? |
|---|---|---|
invalid_value | A field fails its rules: missing, wrong type, empty, too long, a control character, an unknown event_name, event_time more than 300 seconds in the future, value_micros out of range, currency other than USD, value_micros without currency, an unknown key, or an event that is not an object. | No. Fix the event, then send it. |
unknown_click | click_id does not match a click on a campaign this key can reach. For the organization key that is every ad account in the organization; for an advertiser key, its own ad account. An event sent within moments of its click can also get this code. | Yes, later, for a recent click. Otherwise check that click_id is the az_cid from the landing URL and that the key reaches the campaign’s ad account. |
outside_window | event_time is before the click or after the campaign’s attribution window, or the event is sent more than 30 days after the click. | No. |
You can resend the whole batch: accepted events count once.
Request errors
These fail the whole call, which returns no conversion_batch.
{
"error": {
"type": "invalid_request_error",
"code": "invalid_value",
"message": "data holds at most 1000 events",
"param": "data"
}
}| Status | code | When | Retry? |
|---|---|---|---|
400 | invalid_value | data is missing, not an array, empty, or holds more than 1,000 events; the body is not an object; or the body has a top-level key other than data (param names it). | No. Fix the body. |
400 | invalid_json | The body is not JSON, or Content-Type is not application/json. | No. Fix the body. |
401 | invalid_api_key, missing_api_key | The key is missing or invalid, or is a key for another Adzen product. With Authorization: Bearer, or with no key, the body is the error envelope with type authentication_error. With X-API-Key, the body is {"error": "Unauthorized", "message": "invalid API key"}, with no type or code. | No. Fix the key. |
403 | The request comes from an IP address outside the US. | No. Send from the US. | |
409 | idempotency_key_reused, idempotency_key_in_use | Only with an Idempotency-Key header. See Idempotency. | idempotency_key_reused: no, send a new key. idempotency_key_in_use: yes, after Retry-After seconds. |
413 | payload_too_large | The body is over 2 MiB. | No. Send fewer events per call. |
429 | rate_limit_exceeded | Over the rate limit. | Yes, after Retry-After seconds. |
503 | upstream_unavailable | The batch could not be recorded. | Yes. Resend the same batch after a short wait. |
On a 503, resend the whole batch unchanged. Deduplication keeps every
conversion counted once.
Deduplication
A conversion is identified by the combination of click_id, event_name and
dedupe_key. Each combination counts once, whether a resend comes in a later
call or in the same one.
The first write wins. A resend with the same three values and a different
value_micros or event_time is accepted and changes nothing. To record a
different conversion on the same click, send a new dedupe_key; it counts as
a second conversion.
Attribution
| Rule | Value |
|---|---|
| Model | Click-through |
| Window | 7, 14 or 30 days from the click, set per campaign with attribution_window_days; default 30. The window applied is the campaign’s setting when you send the conversion. |
| Reporting deadline | 30 days after the click. Later events are refused with outside_window. |
| Counted on | Valid clicks. A conversion on an invalid click is accepted and stored, and is not counted in insights. |
| Event names | Every event_name counts as one conversion. A lead and a purchase on one click are 2 conversions. |
| Value | Every value_micros adds to conversion_value_micros. Only purchase values add to attributed_sales_micros. |
Accepted conversions appear in insights within about 5 minutes. An insights
row is final 30 days after its end_time; see
Finality.
Conversions are reported, not billed.
Rate limits
600 requests per minute per key on this endpoint. 1,200 requests per minute per key across the whole Ads API. See Rate limits.