Skip to content

Errors and retries

Errors use application/problem+json (RFC 9457). Branch on code. Quote traceId when contacting support.

{
"type": "https://docs.smartcast.media/errors/screen-unavailable",
"title": "Some screens cannot take this campaign",
"status": 409,
"code": "SCREEN_UNAVAILABLE",
"detail": "1 of 2 screens is full on 2026-12-03.",
"errors": [{ "pointer": "/screenIds/1", "code": "NO_CAPACITY", "date": "2026-12-03" }],
"traceId": "7f3c9a1e2b"
}
Code Status What to do
UNAUTHORIZED 401 Get a new token and retry
FORBIDDEN 403 The application lacks the scope. Do not retry
NOT_FOUND 404 Check the id. Other partners’ records also return this
VALIDATION_FAILED 422 Fix the fields listed in errors
IDEMPOTENCY_KEY_REUSED 422 Use a new key for a different request
INVALID_STATE 409 Read the resource, then decide
NOT_READY_TO_SUBMIT 409 Complete what errors lists
SCREEN_UNAVAILABLE 409 Choose other screens or dates
DUPLICATE_EXTERNAL_REF 409 Find the existing record by externalRef
PRECONDITION_FAILED 412 Read again for a new ETag, then retry
PAYLOAD_TOO_LARGE 413 Send a smaller body. Creatives are limited to 100 MB, other bodies to 10 MB
RATE_LIMITED 429 Wait for Retry-After
INTERNAL_ERROR 500 Retry with backoff
SERVICE_UNAVAILABLE 503 The API is briefly unavailable. Wait for Retry-After
PROVIDER_UNAVAILABLE 503 A screen provider could not answer. Wait for Retry-After

POST requests that create something require an Idempotency-Key. Generate one per operation and reuse it when retrying. For 24 hours, the same key and body return the original response instead of creating a duplicate.

Submit, withdraw, cancel and upload-complete are safe to retry without a key: if the resource is already in the target state, you get it back as it stands.

Reads of a campaign return an ETag. Send it as If-Match on PATCH. If someone changed the campaign in between, you get 412 rather than overwriting their change.

Limits are per application. Responses carry RateLimit-Policy and RateLimit headers. Over the limit you get 429 with Retry-After.

Lists return { "data": [...], "nextCursor": "..." }. Pass nextCursor as cursor until it is null. Treat cursors as opaque.