VALIDATION_ERROR400
One or more fields in the request body were not acceptable.
Why: A field is missing, the wrong type, or outside its allowed range.
Fix: Read `error.details.fields`. It is keyed by field name and names the problem with each one.
Extra detail: `fields`: an object mapping each bad field name to its problems.
INVALID_JSON400
The request body was not valid JSON.
Why: Usually a trailing comma, a single-quoted string, or a body sent with no `Content-Type: application/json` header at all.
Fix: Serialise the body with a real JSON encoder rather than string concatenation.
UNSAFE_DESTINATION422
We will not shorten that destination.
Why: The URL uses a scheme we do not allow, points at a private network address, or matched a malware or phishing list.
Fix: Use a public `http:` or `https:` URL. If you believe the block is wrong, contact support with the exact URL.
SLUG_UNAVAILABLE409
That short link already exists on that domain.
Why: Slugs are unique per domain, not globally. The same slug can exist on two different domains.
Fix: Pick another slug, or omit `slug` entirely and we will generate an unused one.
BARCODE_FAILED400
The barcode could not be produced from those parameters.
Why: Each symbology has strict rules about length, character set and check digits. EAN-13 needs exactly thirteen digits; Code 39 refuses lowercase.
Fix: Read the message — it names the rule that failed — and correct the data or pick a symbology that can encode it.
INVALID_PARAMS400
The barcode parameters are not usable.
Why: Either no symbology was named, or the data contains characters the named symbology has no way to encode.
Fix: Name a supported symbology and check the data against its character set and length rules.
NO_TITLE400
This collection needs a title before it can be created.
Why: The title field was missing, or present but empty. A whitespace-only value counts as empty.
Fix: Send a title with at least one non-whitespace character in it.
SLUG_TAKEN409
That page slug is already in use.
Why: Page slugs are unique within a workspace. An archived page still holds its slug, which is the case people do not expect.
Fix: Pick a different slug, or delete the page holding it. Archiving is not enough to free one.
INVALID_TRANSITION409
That approval action does not apply to the page's current state.
Why: Approval moves through fixed states in order. You cannot approve a page that was never submitted, or submit one that is already approved.
Fix: The message names the current state. Pick the action that follows it, or read the page's approval history to see how it got there.
PACK_NOT_READY400
The template pack is not complete enough to publish.
Why: A pack needs a name and at least one template before anybody could usefully install it. The message names which of those is missing.
Fix: Fill in what the message names, then publish again. The pack is saved as a draft in the meantime.
TEST_RUNNING409
An A/B test is already running on this page.
Why: Two overlapping tests split the same traffic, and neither result can then be attributed to either change.
Fix: End the current test first. Its results stay available after it ends, so nothing is lost by stopping it.
UTM_CONVENTION422
The UTM values break this workspace's naming convention.
Why: The workspace enforces a convention so campaign reporting stays consistent across everyone using it. The message names the rule that failed.
Fix: Follow the convention, or relax it in the workspace settings if it is getting in the way more than it helps.
BAD_URL400
That is not a valid web address.
Why: The value could not be parsed as a URL at all — usually a missing scheme or a stray space.
Fix: Send a complete URL including the https:// prefix, and trim any surrounding whitespace.
BLOCKED_HOST400
We will not fetch that address.
Why: It resolves to a private, loopback or link-local address, or it does not resolve at all. Fetching those would let a request reach networks it has no business in — including our own internal ones.
Fix: Use a publicly reachable address. A tunnel service works if you need to expose something running locally.
FETCH_FAILED400
The page did not answer successfully.
Why: It returned an error status, which the message includes. A 403 usually means a bot filter; a 404 usually means a typo.
Fix: Open the address in a private browser window without signing in. If it fails there too, that is what we are seeing.
NOTHING_TO_IMPORT422
We found no links on that page.
Why: The page builds its links in the browser after load. We read the HTML exactly as the server sends it, and there were no links in it yet.
Fix: Add the links by hand, or import from a page that renders its links server-side.
ENDPOINT_PAUSED409
The endpoint is paused, so a replay would go nowhere.
Why: An endpoint pauses itself after repeated failures. Replaying into a paused endpoint would fail again and count as another failure, pushing it further from recovery.
Fix: Send a test ping to confirm the receiver is healthy, switch the endpoint back on, then replay.
CONFLICT409
That affiliate is already enrolled on this page.
Why: A second enrolment would split their attribution across two rows, so neither would show their real earnings.
Fix: Nothing to do — they are already enrolled and their existing referral code still works. Update the existing enrolment if you meant to change its terms.
OWNS_SHARED_WORKSPACE409
You own a workspace that other people are in.
Why: Deleting the account would take the workspace and everyone else's work with it. We will not do that on one person's say-so.
Fix: Transfer ownership of the workspace named in the message to another member, then request deletion again.
ERASURE_BLOCKED409
The erasure request cannot proceed yet.
Why: Something has to be resolved first — usually an active subscription, or a workspace you own that other people are in. The message names it.
Fix: Resolve what the message names, then request erasure again. Nothing has been deleted in the meantime.
DUPLICATE_KEY409
A feature flag with that key already exists.
Why: Flag keys are unique within a workspace, because evaluation looks a flag up by key and two matches would make the result arbitrary.
Fix: Update the existing flag rather than creating a second one, or pick a key that is not taken.
MISSING_KEY400
No flag key was given to evaluate.
Why: The endpoint evaluates named flags and was given no names, so there is nothing for it to answer.
Fix: Add ?key=your-flag-key to the query string. Repeat the parameter to evaluate several flags in one request.
PLAYGROUND_REFUSED400
The documentation playground would not run that request.
Why: A path parameter was left empty, or a destructive call was not confirmed. The playground only runs endpoints that appear in this reference, so it can never reach one the documentation does not describe.
Fix: Read the message — it names the specific reason — and fill in what it asks for.
UNKNOWN_API_VERSION400
The Ryabi-Version header names a version we do not have.
Why: Usually a typo. An unknown version is refused rather than ignored, because a pin you believed in that silently did nothing is worse than no pin at all.
Fix: Use one of the versions listed on the changelog page, or leave the header off entirely to track the current version.
MISSING_CONTENT400
No page content was sent to link.
Why: The body had no `content` field, or it was empty. There is nothing to search for keywords in.
Fix: Send the page as `{ "content": "<p>…</p>" }`.
INVALID_FORMAT400
`format` must be auto, html or markdown.
Why: An unrecognised value. It is refused rather than guessed, because writing Markdown link syntax into HTML — or the reverse — corrupts the file rather than producing a wrong link.
Fix: Leave `format` off to detect it, or send exactly html or markdown.
INVALID_AT400
`at` is not a date we can read.
Why: `at` pins the moment scheduled rules are judged against, so a build that runs either side of a campaign boundary produces the same output. An unreadable value is refused rather than silently treated as now.
Fix: Send an ISO 8601 date-time, for example 2026-12-31T23:59:59Z.