Ads
An ad is the creative and its landing page. It takes its price, surfaces and geo targets from its ad set.
On the ai and ugc surfaces, Adzen uses your copy as written. On static,
Adzen writes the call to action for each publisher page, using your cta as
the starting point.
Which creative fields a placement shows depends on the placement’s ad format.
body, price and the image appear only on formats that have a slot for them.
The ad object
{
"id": "ad_2864",
"object": "ad",
"ad_set_id": "adset_8271",
"external_id": "cr-99812",
"name": "Water heaters, same day",
"status": "active",
"review_status": "approved",
"effective_status": "active",
"serving_issues": [],
"creative": {
"brand_name": "Acme Home Services",
"title": "Same-day water heater repair",
"body": "Licensed Dallas plumbers. Upfront pricing.",
"cta": "Book a plumber",
"price": "From $89",
"target_url": "https://acme.example/water-heaters",
"file_id": "file_5120"
},
"created_time": 1791590400,
"updated_time": 1791590400
}| Field | Type | Rules |
|---|---|---|
ad_set_id | string | Required on create. adset_8271 or 8271. Cannot change. |
name | string | Optional. 1 to 256 characters with no control characters. For your reference; never shown to readers. null clears it. |
external_id | string | Optional. 1 to 256 characters with no control characters. Unique within the ad account. null clears it. |
creative | object | Required on create. |
creative.brand_name | string | Required. Up to 100 characters. |
creative.title | string | Required. The headline. Up to 120 characters. On the ugc surface, a title over 120 bytes in UTF-8 is shortened at a word and ends in …. Keep it to 120 bytes to show it in full everywhere. |
creative.body | string | Optional. One or two sentences, up to 500 characters. |
creative.cta | string | Optional. The call to action, like "Book a plumber". Up to 50 bytes in UTF-8. Defaults to "Learn more". |
creative.price | string | Optional. Like "From $89". Up to 40 characters. Shown as written on formats with a price slot. |
creative.target_url | string | Required. Starts with https:// and has a host. Up to 2,048 characters. Any domain, like a tracking redirect. |
creative.file_id | string | Optional. An image from POST /files in the same ad account as the ad, sent as a string like "file_5120". |
status | string | Read-only: active, paused, archived. Change it with the status endpoints. |
review_status | string | Read-only: in_review, approved, rejected. |
rejection_reasons | string[] | Read-only. On an ad, this field is in the object only when review_status is rejected, and absent otherwise (the ad account always returns it). 1 to 10 reasons written by Adzen’s reviewers, each up to 200 characters. |
effective_status | string | Read-only: active, inactive, archived. See Serving status. |
serving_issues | object[] | Read-only. Why the ad is not serving: { code, message, source: { object, id } }. Empty when effective_status is active. |
created_time | integer | Read-only. Unix seconds. |
updated_time | integer | Read-only. Unix seconds. Moves on any change to the copy, name, external id, status or review, and when effective_status or serving_issues change. See Serving status. |
Creative text
| Rule | Detail |
|---|---|
| Trimming | Every text field is trimmed. Limits count characters after trimming. |
| Content | Not empty, and no control characters. A newline is a control character. |
cta | 50 bytes in UTF-8, so 50 ASCII characters or fewer non-ASCII ones. |
null on update | Clears body, cta (back to “Learn more”), price and file_id. null on brand_name, title or target_url is a 400. |
| Unknown keys | A key not in this table is a 400 invalid_value (unknown parameter creative.<key>). |
A failed rule is a 400 invalid_value with param set to the field, like
creative.title.
Create an ad
POST /ads
Ads are created paused and go to Adzen review. An ad serves when its
effective_status is active. See
Serving status.
| Header | Required | Value |
|---|---|---|
Authorization | Yes | Bearer YOUR_API_KEY |
Content-Type | Yes | application/json |
Idempotency-Key | No | 1 to 255 visible characters. See Idempotency. |
curl -X POST https://api.adzen.ai/v1/ad-manager/ads \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 8d1c-cr-99812' \
-d '{
"ad_set_id": "adset_8271",
"external_id": "cr-99812",
"creative": {
"brand_name": "Acme Home Services",
"title": "Same-day water heater repair",
"body": "Licensed Dallas plumbers. Upfront pricing.",
"cta": "Book a plumber",
"price": "From $89",
"target_url": "https://acme.example/water-heaters",
"file_id": "file_5120"
}
}'The response is 200 with the new ad object, status paused and
review_status in_review.
| Status | code | When | Retry? |
|---|---|---|---|
404 | not_found | No such ad set in your organization (param is ad_set_id), or no such image in the ad’s ad account (param is creative.file_id) | No |
409 | archived | The ad set or its campaign is archived and takes no new ads | No |
409 | ad_account_archived | The ad account is archived | No |
409 | external_id_conflict | The external_id is already used in this ad account | No |
Retrieve, list and update
| Method | Path | Notes |
|---|---|---|
GET | /ads | List; filter with ad_set_id, campaign_id, external_id, status, review_status |
GET | /ads/{id} | |
POST | /ads/{id} | Update name, external_id and the creative. Send only the creative fields you are changing. |
On GET /ads, status must be active, paused or archived, and
review_status must be in_review, approved or rejected. A malformed
ad_set_id or campaign_id, like abc, returns an empty list. GET /ads/{id}
and POST /ads/{id} return 200 with the ad object.
An update with an empty body, {}, changes nothing and returns the ad as it
is. Changes to name and external_id apply right away, with no review.
Editing a live ad
Any update that includes creative sends the ad to in_review, even when the
values are the same as before. The creative fields you send are merged over
the current ones.
| The ad before the edit | While the edit is in review | If the edit is approved | If the edit is rejected |
|---|---|---|---|
| Approved | The approved creative keeps serving. GET returns the edited creative with review_status in_review. | The edited creative serves. | The approved creative keeps serving. GET returns it with review_status rejected and rejection_reasons. |
| Never approved | The ad is not serving. GET returns the edited creative. | The ad can serve. | The ad stays off. |
If Adzen rejects an ad that has no edit in review, the ad stops serving until you send an edit and Adzen approves it.
Status changes, and changes to the ad set’s price or the campaign’s flight dates and budgets, apply right away with no review.
Concurrent changes
One change to an ad runs at a time. An edit or status change that arrives while
another is running on the same ad is a 409 ad_busy. Retry with backoff for
up to 30 seconds.
Change status
| Method | Path |
|---|---|
POST | /ads/{id}/activate |
POST | /ads/{id}/pause |
POST | /ads/{id}/archive |
Each returns 200 with the ad object.
- Archive is final.
activateorpauseon an archived ad is a409archived.archiveon an archived ad returns200. activateon an ad in an archived ad account is a409ad_account_archived.
Images
POST /files
Upload an image and use it on any ad in the same ad account.
| Header | Required | Value |
|---|---|---|
Authorization | Yes | Bearer YOUR_API_KEY |
Content-Type | Yes | multipart/form-data (cURL’s -F sets it) |
Idempotency-Key | No | 1 to 255 visible characters. See Idempotency. |
The body is multipart/form-data with exactly these fields:
| Field | Required | Value |
|---|---|---|
ad_account_id | Yes | An ad account in your organization, like acct_61 |
purpose | Yes | ad_image |
file | Yes | The image: PNG or JPEG, up to 25 MB |
curl -X POST https://api.adzen.ai/v1/ad-manager/files \
-H 'Authorization: Bearer YOUR_API_KEY' \
-F ad_account_id=acct_61 \
-F purpose=ad_image \
-F file=@water-heater.jpgThe response is 200 with the file object. Use its id as
creative.file_id; ads reference images only by id.
{
"id": "file_5120",
"object": "file",
"ad_account_id": "acct_61",
"purpose": "ad_image",
"content_type": "image/jpeg",
"width": 1200,
"height": 1200,
"bytes": 482113,
"created_time": 1791590400
}| Rule | Value |
|---|---|
| Formats | PNG or JPEG |
| Size | Up to 25 MB (26,214,400 bytes) |
| Dimensions | Any. The file object returns width and height in pixels. Square 1200 x 1200 px images display best. Review rejects an image that won’t render well on Adzen’s surfaces. |
| Status | code | When | Retry? |
|---|---|---|---|
400 | invalid_image | The file is empty or over 25 MB; it is not a PNG or JPEG; or its part’s Content-Type names another format or is not a valid type. param is file. | No |
400 | invalid_value | ad_account_id or file is missing, purpose is not ad_image, or the form has another field; param names it | No |
404 | not_found | No such ad account in your organization; param is ad_account_id | No |
A file part with no Content-Type, or application/octet-stream, is accepted
when its bytes are a PNG or JPEG.
GET /files and GET /files/{id}
List the images in your ad accounts, or retrieve one, for example to recover
an id after a timed-out upload. GET /files is a
list, newest first by default; filter with
ad_account_id. Its updated_after filter compares against created_time.
Each item, and the response of GET /files/{id}, is a file object.
Error responses
Errors use the Ads API error body. Authentication
errors, the non-US 403, 429 rate_limit_exceeded and 503
temporarily_unavailable apply to every endpoint and are listed in
Errors.
| Status | code | When | Retry? |
|---|---|---|---|
400 | invalid_value | A field failed validation, is unknown or is read-only; param names it | No |
400 | invalid_json | The body is not JSON | No |
400 | invalid_image | The upload is not a PNG or JPEG of 25 MB or less | No |
404 | not_found | No such ad, ad set, ad account or file in your organization. For a file the creative names, param is creative.file_id. | No |
409 | ad_busy | Another change to this ad is running | Yes, with backoff, for up to 30 seconds |
409 | external_id_conflict | The external_id is already used in this ad account | No |
409 | archived | The ad, or on create its ad set or campaign, is archived and cannot change | No |
409 | ad_account_archived | The ad account is archived; nothing in it can change | No |
409 | managed_by_adzen | Adzen manages this object; it can be read but not changed. | No |
503 | upstream_unavailable | The request did not complete | Yes, with backoff. On a create, resend with the same Idempotency-Key. |