QR endpoints
The customer API has two parts:
/api/qr/codes— a resource API for dynamic QR codes: create, list, read, update, and read scan analytics. Dynamic codes route every scan through ExaRoutes, so they are editable and tracked./api/qr/static— a one-shot renderer for static QR codes. Static codes encode the payload directly, so there is nothing to track or edit. Nothing is stored.
Every endpoint here is authenticated with a Bearer API key. See Authentication.
The id used throughout is the QR code’s shortId (the redirect slug). It is the only
identifier the API exposes.
Create a dynamic QR code
POST /api/qr/codes
Authorization: Bearer exr_live_...
Content-Type: application/json
{
"data": "https://yourcompany.com/spring",
"dataType": "url",
"returnType": "png"
}data is required. dataType defaults to url (other values: text, email, wifi,
vcard, sms, phone, geo). returnType (png or svg) sets the format of the printable
image. Styling fields (shape, margin, colours, logo, error correction) are optional.
Response:
{
"id": "Ab3xK9pQ",
"type": "dynamic",
"dataType": "url",
"destination": "https://yourcompany.com/spring",
"redirectUrl": "https://qr.exaroutes.com/r/Ab3xK9pQ",
"status": "active",
"encrypted": false,
"secure": [],
"createdAt": "2026-05-21T15:00:00.000Z",
"updatedAt": "2026-05-21T15:00:00.000Z"
}The QR pattern encodes redirectUrl. Fetch the printable image separately (see below).
List QR codes
GET /api/qr/codes?limit=20&status=active
Authorization: Bearer exr_live_...Query parameters: limit (1-100, default 25), cursor (from a prior response), type (filter
by dataType), status (active or inactive).
{
"data": [ { "id": "Ab3xK9pQ", "type": "dynamic", "...": "..." } ],
"pagination": { "total": 42, "limit": 20, "cursor": "0", "nextCursor": "20" }
}Pass nextCursor back as cursor to fetch the next page. nextCursor is null on the last
page.
Get one QR code
GET /api/qr/codes/Ab3xK9pQ
Authorization: Bearer exr_live_...Returns a single QR code object, the same shape as the create response.
Update a QR code’s destination
PUT /api/qr/codes/Ab3xK9pQ
Authorization: Bearer exr_live_...
Content-Type: application/json
{
"destination": "https://yourcompany.com/spring-v2"
}The QR keeps its id and printed appearance. Only the redirect target changes. Encrypted,
password-protected, and compliance-locked codes cannot be updated via the API (409); edit
those from the dashboard.
Read scan analytics
GET /api/qr/codes/Ab3xK9pQ/analytics?days=30
Authorization: Bearer exr_live_...days is 1-90 (default 30). Returns a day-wise scan time series and a country breakdown.
Get the printable image
GET /api/qr/codes/Ab3xK9pQ/image
Authorization: Bearer exr_live_...Returns the rendered QR image (image/png or image/svg+xml, whichever format the code was
created with).
Bulk create
POST /api/qr/codes/bulk
Authorization: Bearer exr_live_...
Content-Type: application/json
[
{ "data": "https://yourcompany.com/a" },
{ "data": "https://yourcompany.com/b" }
]Bulk creation is asynchronous. The response is a bulkId. Poll its status:
GET /api/qr/codes/bulk/{bulkId}When the job is done, download the result archive once:
GET /api/qr/codes/bulk/{bulkId}/resultThe result is a one-shot download; it is removed after the first successful fetch.
Render a static QR code
POST /api/qr/static
Authorization: Bearer exr_live_...
Content-Type: application/json
{
"data": "https://yourcompany.com",
"dataType": "url",
"returnType": "svg"
}Static codes are not stored and have no id, no analytics, and no destination updates. The
rendered image is returned inline:
{
"type": "static",
"dataType": "url",
"format": "svg",
"image": "<svg ...>...</svg>"
}For returnType: png the image field is a data: URI.