API Access

API Reference

Every route on the public API, with example requests. See Getting Started for authentication and rate limits.

Conventions

Every route requires an x-api-key header. Whether a request acts on your personal library or your business's shared library is determined entirely by which key you send — there's no separate business URL prefix.

Errors are JSON: {"error": "..."} for a single problem, or {"errors": [{"index": 0, "error": "..."}]} when a batch request fails validation — batch creation is all-or-nothing, so a validation error on any one item means nothing in the batch was created.

A business-scoped key that creates a shared-library item creates it with "status": "draft" — the same review workflow a human teammate's manual entry goes through (see Shared Library & Review Workflow).

Static QR codes

RouteWhat it does
GET /qrcodesList your (or your team's) saved QR codes.
POST /qrcodesCreate one QR code record.
POST /qrcodes/batchCreate up to 50 at once.
DELETE /qrcodes/{qr_id}Delete one.
GET /qrcodes/exportCSV of every record.
curl -X POST .../v1/qrcodes/batch \
  -H "x-api-key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"qrcodes": [
    {"url": "https://example.com/a", "name": "A"},
    {"url": "https://example.com/b", "name": "B"}
  ]}'

# -> 201
{"created": [
  {"qr_id": "...", "url": "https://example.com/a", "name": "A", "style": {}, "created_at": 1785500000, "updated_at": 1785500000},
  {"qr_id": "...", "url": "https://example.com/b", "name": "B", "style": {}, "created_at": 1785500000, "updated_at": 1785500000}
]}

Dynamic QR codes

RouteWhat it does
GET /dynqrcodesList your (or your team's) dynamic QR codes.
POST /dynqrcodesCreate one.
POST /dynqrcodes/batchCreate up to 50 at once.
PATCH /dynqrcodes/{code}Change destination URL, name, or status.
DELETE /dynqrcodes/{code}Delete (soft-delete — stops resolving, doesn't erase scan history).
GET /dynqrcodes/exportCSV of every record.
curl -X POST .../v1/dynqrcodes \
  -H "x-api-key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"destination_url": "https://example.com/landing", "name": "Spring campaign"}'

# -> 201
{"created": [{
  "code": "aB3xY9kQ", "short_url": "https://qordway.com/q/aB3xY9kQ",
  "destination_url": "https://example.com/landing", "name": "Spring campaign",
  "style": {}, "status": "active", "team_id": null,
  "created_at": 1785500000, "updated_at": 1785500000
}]}

Reporting (analytics)

RouteWhat it does
GET /dynqrcodes/analyticsSummary (total/unique scans) for every code you can see.
GET /dynqrcodes/{code}/analyticsFull breakdown for one code — daily counts, country, device, OS, browser.
GET /dynqrcodes/{code}/analytics/exportCSV of every individual scan event for one code.

See Dynamic QR Analytics for what each field means — the API returns the same data the analytics page shows, just as JSON/CSV instead of a chart.

Status codes

CodeMeansWhat to do
200 / 201Success. 201 on creation.
400Validation failed — a bad URL, a missing required field, or a batch over 50.Read the error (or errors[].index) and fix the record. Retrying unchanged will fail identically.
403The key is missing, revoked, or not valid yet — or the account behind it no longer has API access, because its plan changed or a temporary grant expired.If the key is brand new, wait a few minutes for propagation. If the error mentions API access, the key is fine and the plan is the problem — regenerating won't help.
404No such record, or it isn't in the library this key is scoped to.Check the ID, and check whether you're using a personal key against a business record or vice versa.
429Rate limit or daily quota exceeded.Back off and retry. Batch your writes rather than looping single creates.

Frequently asked questions

How do I work with my business's shared library instead of my own?

Send a business-scoped key. The routes are identical — scope is decided entirely by which key you use, so there's no separate prefix and no account switch. Anything a business key creates lands as a draft, the same as a teammate's manual entry.

Why did my whole batch fail because of one bad record?

That's intentional — batch creation is all-or-nothing. It means a retry is always safe: fix the record identified by errors[].index and resend the entire batch, with no risk of duplicating the records that were already valid. Partial success would leave you reconciling what did and didn't get created.

Does deleting a dynamic code erase its scan history?

No — DELETE /dynqrcodes/{code} is a soft delete. The code stops resolving and disappears from listings, but its scan history is retained and the short code is never reissued. Export the analytics first if you need the numbers.

Can I create QR code images through the API?

No. Every route here works with records, not artwork — there's no endpoint returning a PNG or SVG. For a dynamic code the response includes short_url, which is what you'd encode when rendering the image yourself.

Are timestamps in my time zone?

No — created_at and updated_at are Unix epoch seconds in UTC. Convert them on your side; the profile time zone setting only affects how the web dashboard groups scans by day.