/api/preview/* use one JSON shape, whatever the endpoint:
Handle errors by
code, and treat a code you don’t recognize by its HTTP status and retryable
flag: new codes may be added during the preview.
A few responses carry no JSON body: a path that doesn’t exist (404), a method a route doesn’t
support (405, for example DELETE on an Instagram rule), and, rarely, a 5xx when authentication
or rate limiting fails unexpectedly. Treat any 5xx whose body you can’t parse as retryable.
Retrying
retryable: true: wait and send the same request again. UseretryAfterSeconds(or theRetry-Afterheader on a429) when present; otherwise back off exponentially with jitter, starting at a second or two. Cap it at about five attempts, never retry in a tight loop, and wait at least a second even whenretryAfterSecondsis0.retryable: false: the same request will fail the same way. Fix the input, re-read the resource, or ask a person to act in the dashboard, as the tables below say.- Creates with an
Idempotency-Key(POST /api/preview/documents,POST /api/preview/instagram/rules,POST /api/preview/segments): a retryable failure the create reports itself (for example a retryableNOTION_FETCH_FAILEDorINSTAGRAM_UNAVAILABLE) releases the key, so retry with the same key and body. A non-retryable failure is stored against the key: resending the same key and body returns the same error again. After fixing the request, send it with a new key (reusing the old key with a different body is409 IDEMPOTENCY_KEY_CONFLICT). - A create that fails with
500 INTERNAL_ERRORmay keep holding its key for up to a minute. Retry with the same key and body. While the earlier attempt still holds the key you get409 IDEMPOTENCY_KEY_IN_PROGRESS: waitretryAfterSeconds(3) between tries. It clears within about a minute, after which the retry runs as a fresh request; stop and investigate if it hasn’t cleared after two minutes.
Rate limits
Each account can make 60 requests per minute across all/api/preview/* routes, however many keys
it has. Over the limit, the API answers 429 RATE_LIMITED with these headers:
These headers are sent only on the
429. On the idempotent creates, a replay of a key that was
already used, a conflict and an in-progress answer don’t count toward the limit.
Requests running at once
An account can also have at most 10 requests running at the same moment across all/api/preview/*
routes, however many keys it has. The eleventh is refused with 429 TOO_MANY_CONCURRENT_REQUESTS
and Retry-After: 1, and none of the X-RateLimit-* headers. It counts requests that have not
finished, so it can apply while you are well under 60 requests per minute: send requests one after
another, or a few at a time, instead of all at once. A refused request did nothing, so it is safe to
retry as is, but wait the Retry-After pause first: the refused request still counts toward the 60
requests per minute, except on the idempotent creates, which spend that budget only once a request is
accepted.
Error codes
Authentication and access
These can come from any endpoint.Rate limits and availability
The API can also answer
502 with BATCH_SCHEDULE_FAILED or INSTAGRAM_UNAVAILABLE (see
Instagram); both are retryable.
Request format
Idempotency
POST /api/preview/documents, POST /api/preview/instagram/rules and POST /api/preview/segments
require an Idempotency-Key header. POST /api/preview/segments/preview does not take one: it saves
nothing, so repeating it is always safe.
Documents
Contacts
Groups
A group rule is checked the same way byPOST /segments and POST /segments/preview. A
refusal here never created or changed anything. The rule format is on
Group conditions.
Instagram write errors that fall into none of these codes are
500 INTERNAL_ERROR (retryable).