openapi-management.json.
Authentication and tokens
Every call sends a management token in theAuthorization header:
- An owner creates it in Settings → Management tokens; it is shown once. It acts on the whole organisation, with no finer rights, and an owner’s token does not expire.
- Revoke it there once the script is done, or at once if it may have leaked: the next call is a
401. - A management token (
ds_mgmt_…) is not an API key (ds_live_…): each API refuses the other’s (keys and tokens). api.shftd2.comonly (app.shftd2.comanswers404); cookies are never read.
account.id is also your partner_id on the delivery API.
Limits and errors
Writes sendContent-Type: application/json and a JSON object ({} for a DELETE) of at most 262,144
bytes; unknown fields are refused, nested ones included. Responses are JSON, Cache-Control: private, no-store; lists are {"items": [...]}, without pagination. Errors are
{"error": {"code", "message", "field"?}}: branch on code and field, message is for people.
Nothing is written until every check passes, in this order: token and limits, body (
400, 422), the
object in the path (404), stored state (403, 409, 422).
- Per token: 120 requests per minute, of which at most 60 writes (
PUT,POST,DELETE). - Per IP: 30 failed authentications and 600 requests with a well-formed token per minute.
RateLimit-Policy: "token";q=120;w=60, "write";q=60;w=60on every response; nothing gives the calls left.- Counters are per Cloudflare location, so approximate: one write per second stays well within.
References
A fragment’s address is its site’s domain plus its reference, e.g./1234567/news-site/organic/politics.
{domain}is the bare, lowercase domain;www.news-site.exampleandnews-site.exampleare two sites.- A reference is case-sensitive: 1 to 200 characters among
A-Z a-z 0-9 / _ - . :, no segment.or... - In a path, encode it once with
encodeURIComponent, slashes included: double-encoded (%252F…) is a422, unencoded slashes a404. - In a JSON body (
ref,default_fragment_ref,routes[].ref,fragments[].ref), send it plain. - A fragment listed with
"ref": nullis out of the API’s reach until you give it a reference in the console. A reference never changes through the API: it is the address.
Writes and idempotency
PUTon a site or a fragment creates or updates it (201, then200): a script can run twice.PUT …/routesgives every rule a newid; a secondDELETEof a rule is a404.- Clearing the default and revoking a key are repeatable (
200, same state). POST …/routesanswers409if the rule exists;POST /v1/keyscreates a key on every call.
Sites and fragments
PUT /v1/sites/{domain} registers or updates a site: name absent keeps it, "" clears it;
default_fragment_ref names an active fragment, so not in the creating call; domain in the body is
refused.
PUT /v1/sites/{domain}/fragments/{ref} writes the whole fragment: name (required), lang,
description, status (absent: active on creation, unchanged on update); see
sites and fragments. key_values is accepted for existing integrations, outside the
documented contract.
Pausing the site default or a rule’s target says so in warnings, e.g. ["site default", "target of 2 rules"].
Defaults and routing rules
How rules and the default resolve a page: resolution.PUT /v1/sites/{domain}/default-fragmentwith{"ref": …}sets an active fragment of the site;DELETEwith{}clears it and keeps the fragment.PUT …/routeswith{"routes": [{"path_prefix", "match", "ref"}]}replaces the rules;POST …/routesadds one (422once the site has 200);DELETE …/routes/{id}removes one.- Paths come back in their stored, canonical form.
Cards and eligibility
GET /v1/cards lists your cards and the platform cards ("account_id": null), in every status.
GET and PUT /v1/cards/{id}/eligibility read and replace a card’s fragments, named by domain and
reference, your organisation’s only. What eligibility means: cards. A platform card’s list
can be read, not written (403), and an empty one is not conclusive: other organisations’ choices are
never shown.
Delivery keys
POST /v1/keyswith an optional{"name"}answers201with the full key inkey. The key is in that response only: store it at once, out of logs and tickets; only itsprefixis listed after.- If that response is lost, do not retry: list the keys, revoke the one you never received, create another.
GET /v1/keyslists every key, revoked ones included.DELETE /v1/keys/{id}with{}revokes one.
Prepare a client
A script that seeds or syncs an organisation:- Reads the token from its environment, never an argument or a file, and never prints it.
- Calls
GET /v1/mefirst and stops unlessaccount.idis the intended organisation. - Writes only what differs from what it read (paths and domains in stored form).
- Writes site by site: site, fragments, default, rules. Eligibility comes last, one complete list per card, and not at all if an earlier step failed.
- Spaces its writes and waits for
Retry-Afteron a429. - Creates an API key only when needed, in its own step, and keeps the secret.
- Changes nothing on a second run.
- Ends with the token revoked in Settings → Management tokens.
Console-only actions
- Creating, editing, activating, archiving or deleting a card.
- Deleting a site or a fragment; through the API, pause the fragment instead.
- Deleting a revoked API key; managing management tokens (owners only) and members.

