Reticle

Reticle QR Code API

Authentication

Every request is authenticated with a bearer API key, minted from your account page. A key is shown to you exactly once at creation time; Reticle stores only a hash of it, never the key itself, so if you lose it there's nothing to recover, only a new key to mint. Each account can hold a small number of named keys at once (see the limits table below) and revoke any of them individually at any time; a revoked key stops working on its very next request.

Send the key as Authorization: Bearer rk_live_<your key>. The API is server-to-server by design: it sends no CORS headers, so a browser page cannot call it directly, which is deliberate, since a page that could would be shipping your bearer key to anyone who opens dev tools. Call it from a server, a script, or a scheduled job instead.

Any request with a body must send valid JSON with Content-Type: application/json. A malformed body (invalid JSON) is rejected with a plain 400 before it reaches the API's own logic. The wrong content type still reaches the handler, which reports it with the same JSON error shape used everywhere else, described below.

Quick start

Create a dynamic link that redirects to a destination URL:

curl -X POST https://reticle.cloud/api/v1/links \
  -H "Authorization: Bearer rk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"destination": "https://example.com/menu", "name": "menu"}'

which returns:

{
  "slug": "aB3xY9",
  "shortUrl": "https://open-qr.link/aB3xY9",
  "kind": "redirect",
  "destination": "https://example.com/menu",
  "name": "menu",
  "active": true,
  "labels": [],
  "customSlug": null,
  "linkDomain": null,
  "createdAt": "2026-08-12T19:04:05.000Z",
  "scanCount": 0,
  "lastScanAt": null
}

That response shape, the "public link" shape, is what every endpoint below returns for a link: a fixed, closed set of fields. Anything not in that list (routing rules, password hashes, Safe Browsing verdicts, the owner id) is never returned by the API, no matter what's on the underlying document. Timestamps are always ISO 8601 UTC strings, or null when not yet set.

Endpoints

All six routes live under https://reticle.cloud/api/v1:

Method + pathWhat it does
POST /linksCreate a new redirect link from { destination, name? }.
GET /linksList your links, ordered by slug, not by creation date. Paginate with ?limit= (default 100, max 500) and ?cursor=.
GET /links/{slug}Read one link you own.
PATCH /links/{slug}Update destination, name, and/or active. Any other field in the body is rejected.
DELETE /links/{slug}Delete a link and its scan history.
GET /links/{slug}/statsAggregate scan stats: total count, last scan time, and per-day/device/hour/country breakdowns.

Reading works for every kind of link: GET /links/{slug} and its /stats return a link's public shape or its stats whether the link is a redirect, a file link, a bio page, or a dynamic vCard. Writing is redirect-only: PATCH and DELETE both return wrong_kind on any link that isn't a plain redirect. A slug that doesn't exist, or belongs to a different account, always returns not_found, never a permission error, so the API never confirms whether someone else's link exists.

Errors

Every error response is JSON, in the same shape:

{ "error": { "code": "rate_limited", "message": "Too many requests. Please slow down and try again." } }
CodeStatusMeaning
unauthorized401The API key is missing, invalid, or revoked.
plan_required403The account is not on an active Pro plan, or (on create) its email is not yet verified.
not_found404No such link, or the slug belongs to a different account.
method_not_allowed405That HTTP method isn't supported on this path.
wrong_kind409This link isn't a redirect link, so it can't be patched or deleted through the API (reading it, and reading its stats, still work).
invalid_request422The request body is missing a required field, has the wrong type, or includes an unknown field.
link_limit_reached422The account has reached its dynamic link limit.
unsafe_destination422The destination URL failed a safety check.
rate_limited429Too many requests; the response includes a Retry-After header.
internal500Something went wrong on our end. Please try again.

Rate limits

Two ceilings apply, and they're separate budgets: an overall request ceiling that covers every call you make, and a smaller creation budget that link creation shares with the ordinary create-a-link flow in the app itself (so a script and a signed-in session drawing from the same account draw from the same creation budget). Both fail open: if the rate limiter itself has trouble, your request still goes through rather than getting refused by an outage on our side. A request that's over a limit gets back 429 rate_limited with a Retry-After header telling you how many seconds to wait.

LimitAmount
API keys per account5
Requests per hour, all endpoints combined3600
Requests per day, all endpoints combined20000
Link creations per hour250
Link creations per day400

Frequently asked questions

Is the API included in Pro?

Yes. The API is included with Reticle Pro at no extra cost, whether you're on the $12 a month or $99 a year plan. There is no separate API tier and no metered usage billing on top of the subscription.

Can I create file or bio links through the API?

No. Version 1 of the API creates and manages ordinary redirect links only. File QR codes, link-in-bio pages, and dynamic vCards stay UI-only for now; they may be added to a future API version.

What happens to my links if I stop using the API?

Nothing. Links and QR codes you created through the API keep working and keep resolving forever, whether or not you ever call the API again. Printed codes are never tied to ongoing API use.

Is there a free API tier?

No. The QR code generator and static codes are free with no account required, but the API itself requires an active Reticle Pro plan; there is no free tier or trial for API access specifically.

Ready to script your codes? Upgrade to Reticle Pro, then open your account page to mint your first API key.