04
Endpoints
File codes (type: 'file') require a multipart upload and can only be created
from the dashboard — POST /codes rejects them with 400 invalid_request.
GET /api/v1/codes
List every non-archived code owned by the key's organization. Read scope suffices.
curl https://evertag.app/api/v1/codes \
-H "Authorization: Bearer evtg_..."
{
"success": true,
"data": [
{
"id": "b7e6b6b0-2a2f-4a2b-9c3d-8f0a2c1e9a11",
"name": "Table tent",
"slug": "8f3k2a",
"type": "url",
"state": "active",
"destination": "https://example.com/menu",
"config": { "destination": "https://example.com/menu" },
"shortUrl": "https://evertag.app/s/8f3k2a",
"createdAt": "2026-07-01T12:00:00.000Z",
"updatedAt": "2026-07-01T12:00:00.000Z"
}
],
"error": null
}
POST /api/v1/codes
Write scope required. Creates a code and counts against the plan's dynamic-code limit.
| Field | Type | Notes |
|---|
name | string | required, non-empty |
type | string | one of url, vcard, wifi, linkpage, menu, appstore (not file) — see Code types below |
config | object | shape depends on type, validated server-side |
curl -X POST https://evertag.app/api/v1/codes \
-H "Authorization: Bearer evtg_..." \
-H "Content-Type: application/json" \
-d '{
"type": "url",
"name": "Table tent",
"config": { "destination": "https://example.com/menu" }
}'
// 201 Created
{
"success": true,
"data": {
"id": "b7e6b6b0-2a2f-4a2b-9c3d-8f0a2c1e9a11",
"name": "Table tent",
"slug": "8f3k2a",
"type": "url",
"state": "active",
"destination": "https://example.com/menu",
"config": { "destination": "https://example.com/menu" },
"shortUrl": "https://evertag.app/s/8f3k2a",
"createdAt": "2026-07-01T12:00:00.000Z",
"updatedAt": "2026-07-01T12:00:00.000Z"
},
"error": null
}
GET /api/v1/codes/:id
Read a single code. Read scope suffices. A foreign or unknown id returns 404 not_found.
curl https://evertag.app/api/v1/codes/b7e6b6b0-2a2f-4a2b-9c3d-8f0a2c1e9a11 \
-H "Authorization: Bearer evtg_..."
{
"success": true,
"data": {
"id": "b7e6b6b0-2a2f-4a2b-9c3d-8f0a2c1e9a11",
"name": "Table tent",
"slug": "8f3k2a",
"type": "url",
"state": "active",
"destination": "https://example.com/menu",
"config": { "destination": "https://example.com/menu" },
"shortUrl": "https://evertag.app/s/8f3k2a",
"createdAt": "2026-07-01T12:00:00.000Z",
"updatedAt": "2026-07-01T12:00:00.000Z"
},
"error": null
}
PATCH /api/v1/codes/:id
Write scope required. Send exactly one of config or state.
| Field | Type | Notes |
|---|
config | object | revalidated against the code's (immutable) type |
state | string | 'active' or 'paused' only — 'redirect_only' is a system-managed state and is rejected with 400 invalid_request if requested explicitly |
curl -X PATCH https://evertag.app/api/v1/codes/b7e6b6b0-2a2f-4a2b-9c3d-8f0a2c1e9a11 \
-H "Authorization: Bearer evtg_..." \
-H "Content-Type: application/json" \
-d '{ "state": "paused" }'
{
"success": true,
"data": {
"id": "b7e6b6b0-2a2f-4a2b-9c3d-8f0a2c1e9a11",
"name": "Table tent",
"slug": "8f3k2a",
"type": "url",
"state": "paused",
"destination": "https://example.com/menu",
"config": { "destination": "https://example.com/menu" },
"shortUrl": "https://evertag.app/s/8f3k2a",
"createdAt": "2026-07-01T12:00:00.000Z",
"updatedAt": "2026-07-01T12:05:00.000Z"
},
"error": null
}
DELETE /api/v1/codes/:id
Write scope required. Archives the code — a terminal state. Archiving
removes it from the edge KV lookup, so the short URL stops resolving; there is no API to
reverse it.
curl -X DELETE https://evertag.app/api/v1/codes/b7e6b6b0-2a2f-4a2b-9c3d-8f0a2c1e9a11 \
-H "Authorization: Bearer evtg_..."
{
"success": true,
"data": {
"id": "b7e6b6b0-2a2f-4a2b-9c3d-8f0a2c1e9a11",
"name": "Table tent",
"slug": "8f3k2a",
"type": "url",
"state": "archived",
"destination": "https://example.com/menu",
"config": { "destination": "https://example.com/menu" },
"shortUrl": "https://evertag.app/s/8f3k2a",
"createdAt": "2026-07-01T12:00:00.000Z",
"updatedAt": "2026-07-01T12:10:00.000Z"
},
"error": null
}
GET /api/v1/codes/:id/qr.svg
Render the code's QR as SVG. Read scope suffices. Optional ?size= in pixels, clamped to 64–2048 (default 256).
The render reflects whatever design — colors, module/eye shape, center logo — is
currently saved for the code in the dashboard's Design panel; codes with no saved design
render with the classic black-on-white defaults. Mutating a code's design via the API is
on the roadmap and not yet supported — for now, set it from the dashboard.
Not <img>-embeddable. This endpoint requires the same Authorization bearer header as every other call — browsers do not attach
custom headers to an <img src> request, so hotlinking this URL directly
in HTML will fail with 401 unauthorized. Fetch it server-side (or with curl) and serve or embed the bytes yourself.
curl -o qr.svg "https://evertag.app/api/v1/codes/b7e6b6b0-2a2f-4a2b-9c3d-8f0a2c1e9a11/qr.svg?size=512" \
-H "Authorization: Bearer evtg_..."
Exception to the envelope: on success this returns the raw SVG body with content-type: image/svg+xml — not the JSON envelope. Errors (e.g. unknown or
foreign id) still return the standard 404 not_found JSON
envelope.
<!-- 200 OK, content-type: image/svg+xml, cache-control: private, max-age=300 -->
<svg width="512" height="512" viewBox="0 0 512 512" ...>...</svg>
GET /api/v1/codes/:id/stats
Lifetime scan totals plus a daily series. Read scope suffices. Optional ?days=, clamped to 1–90 (default 14).
curl "https://evertag.app/api/v1/codes/b7e6b6b0-2a2f-4a2b-9c3d-8f0a2c1e9a11/stats?days=7" \
-H "Authorization: Bearer evtg_..."
{
"success": true,
"data": {
"scans": 142,
"uniques": 98,
"series": [
{ "date": "2026-06-25", "scans": 12, "uniques": 9 },
{ "date": "2026-06-26", "scans": 20, "uniques": 15 }
]
},
"error": null
}