QRdx
HelpGuidesDevelopersReact librarySelf-hosting

Errors

Every error the QRdx API returns, with its HTTP status, what it means and how to fix it.

Every REST API error is JSON with the same shape, whichever endpoint returns it:

{
  "code": "INSUFFICIENT_SCOPE",
  "message": "This token needs the 'codes:write' scope. Add it to your app and ask for it when the user authorizes.",
  "status": 403,
  "docs": "https://qrdx.dev/docs/developers/rest-api#endpoints"
}
FieldWhat it is
codeA stable, machine-readable code from the table below. Branch on this.
messageWhat went wrong and how to fix it, for people. The wording may change.
statusThe HTTP status, repeated.
docsA page that explains the fix, when there is one.
dataExtra detail, on some errors. VALIDATION_ERROR lists each problem in data.details.

A validation error names every field that failed:

{
  "code": "VALIDATION_ERROR",
  "message": "Invalid request body",
  "status": 400,
  "data": {
    "details": [
      { "path": "destinationUrl", "message": "Enter a full URL, starting with https://" }
    ]
  }
}

The image API reports query parameters as { "param", "message" } instead of { "path", "message" }.

Error codes

StatusCodeMeaningFix
400VALIDATION_ERRORThe body, query or path failed validation. data.details lists each problem as { path, message } ({ param, message } on the image API).Correct the fields listed in data.details and send the request again.
400INVALID_SLUGThe custom back-half (slug) breaks a rule: a reserved word, or the same back-half twice in one request.Choose another back-half. The message names the rule.
400TOO_MANY_CODESMore than 100 codes in one request. The body schema normally rejects this first, as VALIDATION_ERROR.Send at most 100 codes per request.
400DOMAIN_NOT_VERIFIEDdomainId points to a custom domain that isn't verified yet.Finish verifying the domain on the Domains page, or leave domainId out.
400SID_REQUIREDA conversion without the qrdx_sid of the scan (from the browser), or without sid or code (from a server).Send the qrdx_sid the short link added to your page URL, or, with a token, the code id as code.
401UNAUTHORIZEDNo credentials: the request has no Authorization: Bearer header (and no QRdx browser session).Send an OAuth access token as Authorization: Bearer <token>.
401INVALID_TOKENThe access token is unknown, expired (tokens last one hour) or revoked.Get a new access token with your refresh token, or send the user through authorization again.
402PLAN_REQUIREDThe feature isn't on the workspace's plan: bulk creation, custom back-halves and custom domains need Pro; conversions and hooks need Business.Upgrade the workspace, or leave the feature out of the request.
402LIMIT_REACHEDThe workspace has as many active dynamic codes as its plan includes (10 on Free).Archive a code (archived codes don't count) or upgrade to Pro for unlimited codes.
403INSUFFICIENT_SCOPEThe token is valid but lacks the scope this endpoint needs.Add the scope named in the message to your app and ask for it when the user authorizes.
403FORBIDDENThe caller may not do this: a team member deleting a code someone else created, a team member managing hooks, or a browser-session write from another site.Ask a team owner or admin, or call the API with an access token from your server.
403CONVERSIONS_OFFA browser conversion for a code that doesn't have conversion tracking turned on.Turn on conversion tracking for the code, or report the conversion from your server with a token.
403LIMIT_REACHEDThe workspace already has 20 webhook endpoints and hooks.Delete an endpoint or hook you no longer use.
404NOT_FOUNDNo such endpoint, or the code, hook, theme or custom domain doesn't exist in the token's workspace.Check the path and the id. Tokens act on the token owner's personal workspace, not on teams.
404INVALID_SIDThe qrdx_sid is unknown or older than 30 days, the attribution window.Send the qrdx_sid of a recent scan, or report the conversion by code id from your server.
409SLUG_TAKENAnother code already uses that back-half on that domain.Choose another back-half.
413PAYLOAD_TOO_LARGEThe body is over the endpoint's limit: 4 MB for codes, 16 KB for hooks, 8 KB for conversions.Send a smaller body. For codes, a large inline logo is the usual cause.
415UNSUPPORTED_MEDIA_TYPEA write without Content-Type: application/json.Send a JSON body with Content-Type: application/json.
422UNSAFE_DESTINATIONGoogle Web Risk flags the destination URL (malware, phishing or unwanted software).Use another destination. If the flag is wrong, ask Google to review the site.
429RATE_LIMITEDToo many requests: a per-minute limit (only Retry-After is set) or the workspace's daily quota (Retry-After plus X-RateLimit-*).Wait Retry-After seconds. For the daily quota, wait for 00:00 UTC or upgrade the plan.
500INTERNAL_ERRORSomething failed on QRdx's side. It has been logged.Try again in a moment. If it keeps happening, report it with the time of the request.
503SLUG_UNAVAILABLENo free short-link slug could be reserved in time.Send the same request again.
503UNAVAILABLECustom domains aren't set up on this deployment (a self-hosted instance without them).Leave domainId out, or configure custom domains on your instance.

Retrying

  • 429: wait the number of seconds in Retry-After, then send the same request. When the daily quota runs out, the X-RateLimit-* headers say how many requests the plan allows and when the count resets (00:00 UTC). See rate limits.
  • 500 and 503: retry with exponential backoff, starting at about a second.
  • Other 4xx: the same request fails the same way. Fix it first.

Creating codes isn't idempotent: if a POST /v1/codes times out, list your codes before sending it again, or you may create the code twice. Conversions are: send your own id and a repeat returns 200 with duplicate: true.

/v1/me and /v1/themes

These two endpoints send the same body plus the OAuth fields they have always sent, error and error_description (the same text as message), so older clients keep working:

errorcode
invalid_tokenUNAUTHORIZED or INVALID_TOKEN
insufficient_scopeINSUFFICIENT_SCOPE
rate_limitedRATE_LIMITED (daily quota)
not_foundNOT_FOUND (themes)

OAuth endpoints

The OAuth endpoints under https://qrdx.dev/api/oauth (authorize, token, revoke, userinfo) follow the OAuth 2.0 standard instead: { "error", "error_description" }, with error one of invalid_request, invalid_client, invalid_grant, unsupported_grant_type, invalid_token or access_denied. Getting invalid_grant on a refresh means the refresh token was already used (each refresh returns a new one), expired after 30 days, or the user revoked your app: send the user through authorization again. See REST API and OAuth.

Unknown endpoints

A path under /v1 that doesn't exist returns 404 NOT_FOUND as JSON, never an HTML page. The API reference lists every endpoint.

Last updated on

On this page