API error codes

Batch endpoints that return partial success use HTTP 200 with per-item entries in failed (each entry includes code where applicable). See the developer overview for public API details.

Authentication & API keys

CodeHTTPMeaningWhere
INVALID_API_KEY401Missing, empty, or unrecognized Bearer token.Bearer-protected routes (e.g. quota, links, API keys).
API_KEY_REVOKED401The API key was revoked.Bearer-protected routes.
API_KEY_REQUIRES_PAID403API keys are only available on paid plans.Quota, links, API key routes when using Bearer auth.
API_KEY_LIMIT_EXCEEDED403Maximum number of active keys for the plan is reached.POST /api/api-keys
EMAIL_NOT_VERIFIED403Account email must be verified for this action.Session or Bearer routes that require a verified email.

Quota & rate limits

CodeHTTPMeaningWhere
QUOTA_EXCEEDED429 or 200Active short-link limit for the account or anonymous tier; batch responses may include tier and counts on the top-level error, and duplicate this code for remaining indices in failed[] after the first hit.POST /api/links (429). POST /api/links/batch-create failed[] (HTTP 200).
RATE_LIMITED429Too many requests in the current window; Retry-After may be set.Rate-limited routes (link create, batch operations, auth helpers, etc.).

Links

CodeHTTPMeaningWhere
INVALID_URL200Target URL failed validation.POST /api/links/batch-create failed[]
CUSTOM_EXPIRY_NOT_ALLOWED400 or 200Custom expiry is not allowed for this tier.POST /api/links; batch-create failed[]
EXPIRES_IN_DAYS_OUT_OF_RANGE400 or 200expiresInDays is outside the allowed range; minDays/maxDays may be present.POST /api/links; batch-create failed[]
SLUG_ALLOCATION_FAILED200Could not allocate a unique short code after retries.POST /api/links/batch-create failed[]
NOT_FOUND200Slug or link id is not an owned, non-deleted link.POST /api/links/batch-delete and batch-patch failed[] (slugs or linkIds)
SLUG_AMBIGUOUS200 or 409More than one saved link shares this slug (platform vs custom domain). Disambiguate with linkId query on PATCH/DELETE, or send linkIds in batch bodies.PATCH/DELETE /api/links/:slug (409); batch-delete and batch-patch failed[] (200)
RESERVED_SLUG200Slug is reserved (e.g. infrastructure paths).Batch delete/patch failed[]
EDIT_DESTINATION_REQUIRES_PAID403Changing destination URL requires Plus, Pro, or Enterprise.PATCH /api/links/:slug
AB_REQUIRES_PAID400 or 403Weighted split destinations require Plus, Pro, or Enterprise (signed-in).POST /api/links (abVariants), PATCH /api/links/:slug (abEnabled, abVariants, clearAb, etc.)
AB_INVALID_WEIGHTS400Variant weights must sum to exactly 100.PATCH /api/links/:slug with abVariants
AB_INVALID_VARIANTS400abVariants must have 2–12 unique keys (letters, numbers, _ or -).PATCH /api/links/:slug
AB_REQUIRES_TWO_VARIANTS400Cannot enable A/B until two variants exist; send abVariants with keys a and b.PATCH /api/links/:slug with abEnabled: true
AB_WINNER_NOT_FOUND400Declared winner variant is missing; configure variants first.PATCH /api/links/:slug with abWinnerVariant
CUSTOM_DOMAIN_REQUIRES_AUTH403customDomainId requires a signed-in account.POST /api/links
CUSTOM_DOMAIN_REQUIRES_PRO403Custom hostnames require Pro or Enterprise.POST /api/links, POST /api/links/batch-create failed[]
DOMAIN_NOT_OWNED403customDomainId does not belong to this account.POST /api/links, batch-create
DOMAIN_NOT_VERIFIED400Domain must be verified (DNS TXT) before creating links on it.POST /api/links, batch-create

Custom domains

CodeHTTPMeaningWhere
CUSTOM_DOMAINS_REQUIRES_PRO403Custom domains are limited to Pro and Enterprise.GET/POST/DELETE /api/custom-domains, POST …/verify
DOMAIN_LIMIT_REACHED403Account has reached the max verified domains for the plan; max may be present.POST /api/custom-domains
HOSTNAME_RESERVED400That hostname is the platform short-link host.POST /api/custom-domains
HOSTNAME_TAKEN409Another account already registered this hostname.POST /api/custom-domains
DOMAIN_NOT_FOUND404Domain id is missing or not owned by this account.GET/DELETE /api/custom-domains/:id, POST …/verify
DOMAIN_IN_USE409Short links still reference this domain; delete or move them first.DELETE /api/custom-domains/:id
DOMAIN_VERIFICATION_FAILED400TXT record at _linkonda-challenge.<hostname> did not match the token.POST /api/custom-domains/:id/verify

Billing (signed-in)

CodeHTTPMeaningWhere
BILLING_NOT_CONFIGURED503Checkout or billing is not configured on the server.POST /api/billing/checkout, reactivate, portal
UNAUTHORIZED401Sign-in required.POST /api/billing/checkout, reactivate, portal
ENTERPRISE_MANUAL400Enterprise plan changes are handled out of band.POST /api/billing/checkout
USE_PORTAL409An active subscription exists; use the billing portal to change plans.POST /api/billing/checkout
BILLING_PRICE_RESOLVE500Could not resolve a subscription price for the product.POST /api/billing/checkout
NO_SUBSCRIPTION400Nothing to reactivate.POST /api/billing/reactivate
BILLING_REACTIVATE_FAILED400Provider rejected reactivation.POST /api/billing/reactivate
NO_CUSTOMER400No billing customer yet; subscribe first.POST /api/billing/portal