Sandbox
The sandbox answers UGC API requests with ads from a fixed set of fictional advertisers, in the same response format as production.
Base URL
https://sandbox.adzen.aiPaths
| Path | Method | Key | What it does |
|---|---|---|---|
/ugc/v1/process | POST | Yes | Matches a post and returns one ad, or the no-match body. |
/ugc/swagger-ui/ | GET | No | Interactive API docs. |
/ugc/api-docs/openapi.json | GET | No | OpenAPI document. |
Send sandbox requests to /ugc/v1/process. Production uses /v1/ugc/process.
Getting a sandbox key
Ask your Adzen account representative for a sandbox key. Use the sandbox key on the sandbox and your production key in production. Send it in the X-API-Key header.
Example
curl -X POST https://sandbox.adzen.ai/ugc/v1/process \
-H 'Content-Type: application/json' \
-H 'X-API-Key: YOUR_SANDBOX_KEY' \
-d '{
"post_id": "thread-12345",
"message": "Looking for a good plumber in Seattle, our kitchen sink keeps backing up",
"geo_target": { "zipcode": "98103" }
}'The request body is the same as production. See UGC API.
How the sandbox responds
- About 4 in 5 requests return one ad: the closest match from the fictional catalog.
- About 1 in 5 requests, chosen at random, return the no-match body
{ "no_ad_retry_after_seconds": 86400 }. Use these to test your no-match handling. The samepost_idcan return an ad on the next request. - The sandbox applies no length rule to
message. Production returns emptyadsfor a message under 10 characters or over 10,000 bytes. - The sandbox does not return
{ "post_id": "...", "ads": [] }.
Responses use the same format as production. Some values differ from production:
| Field | Sandbox value |
|---|---|
advertiser_name | A fictional brand. |
pricing_model | Always { "type": "CPC", "bid_amount": 0.5 }. |
sponsor_logo_url | Always "". |
ttl_seconds | Always 28800. |
eligibility_ttl | Always 259200. |
Tracking URLs
Sandbox click_through_url and pixel_trackers[].url point at sandbox.adzen.ai and carry {SESSION_ID} only. Use them to test that your code replaces the tracking macros. They are not live URLs: do not request them. Nothing is counted or billed in the sandbox.
Production URLs carry {SESSION_ID}, {EXPERIMENT} and {TREATMENT}. Code that replaces all three works in both environments.
Errors
| Status | Body | When | Retry? |
|---|---|---|---|
400 | text/plain | The body is not valid JSON. | No. Fix the request. |
401 | {"error":"Missing X-API-Key header"} | No key. | No. Add the key. |
401 | {"error":"Invalid X-API-Key"} | The key is not a sandbox key. | No. Check the key. |
401 | {"error":"Profile disabled"} | The key is turned off. | No. Ask your account representative. |
413 | text/plain | The body is larger than 2 MB. | No. Shorten the body. |
415 | text/plain | Content-Type is missing or is not application/json. | No. Set the header. |
422 | text/plain | post_id or message is missing, empty or the wrong type, or a geo_target field has the wrong type. | No. Fix the field. |
5xx | Varies | A temporary error. | Yes, with exponential backoff. |
A request without a valid key gets 401 whatever its body. Branch on the status code, not the body.
Moving to production
- Change the host to
https://api.adzen.ai. - Change the path from
/ugc/v1/processto/v1/ugc/process. - Use your production key.
- Call production from a US IP address. Production returns
403to requests from outside the US, including the click and pixel URLs. The sandbox does not apply this rule. - Handle an empty
adsarray, which the sandbox never returns.