Docs › API Reference

API Reference

Change where a printed QR code points, from your own systems. Create codes in bulk, read scan figures, and keep everything in step with whatever you already run โ€” without anyone opening a dashboard.

The thing worth knowing first

A dynamic QR code encodes a short link, not your destination. The symbol on the packaging never changes; what it resolves to is a row in a database. So repointing a code that is already in the world is a single request, and it takes effect for every copy of it at once โ€” the recalled batch, the seasonal menu, the campaign that moved.

Authentication

Every request carries a bearer token. Create one under API tokens; it is shown once and stored only as a hash, so it cannot be recovered later.

Request example
curl https://lynkarr.com/api/v1/me \
  -H "Authorization: Bearer lyn1_your_token_here"

Plans & Allowances

API access starts on Starter; the free plan has none. The monthly allowance resets on the 1st and is counted per company, not per token, so issuing more tokens does not raise it. Exhausting it returns 402 with a quota_exceeded code.

PlanRequests a monthRequests a minute, per token
FreeNo API access—
Starter10,00060
Business100,000120
Enterprise1,000,000600

Scopes

A token holds exactly the scopes it was given. A write scope does not imply the matching read scope โ€” being explicit means a token's permissions are what the list says, with nothing inferred.

ScopeAllows
codes:read List codes and read their settings.
codes:write Create codes and change where they point. This is what lets a printed code be redirected.
links:read List short links and their destinations.
links:write Create short links and change their destinations.
analytics:read Scan counts, geography, devices and timing.
cards:read List cards, read their details, and read the enquiries people have sent through them.
cards:write Create and edit cards, and publish or unpublish them.
pages:read List pages and read their content and settings.
pages:write Create and edit pages, and publish or unpublish them.
forms:read List forms, read their fields, and read what people have submitted. Submissions are your customers' own details, so grant this deliberately.
forms:write Create and edit forms, and publish or unpublish them.
media:read List files and folders with their names, types and sizes. Uploading is not offered to a token.
gs1:read List GS1 Digital Links and read what each one resolves to.
gs1:write Create and edit GS1 Digital Links and their resolutions.
campaigns:read List campaigns, their members and the tags in use.
campaigns:write Create and edit campaigns and tags, and move things in and out of them.
team:read List who is on the account, their roles and when they last signed in.
team:write Invite people, change their role and remove them. The most dangerous scope there is โ€” a leaked token with this can take over the account โ€” so only an owner can grant it, and even then it can never touch an owner or make anybody one.
High-privilege scope

team:write can invite people, change their role and remove them. Only an owner can grant it. Give it to a token only when the integration cannot work without it.

Endpoints

Base URL: https://lynkarr.com/api/v1. All requests and responses use JSON. The full list, with every parameter, is in the OpenAPI 3.1 specification.

MethodPathScopeDescription
GET /api/v1/me any Confirm a token works and see what it may do.
GET /api/v1/codes codes:read List QR codes. Paginated with limit and offset.
GET /api/v1/codes/:id codes:read One code, including its short link and scan count.
POST /api/v1/codes codes:write Create a code. Returns the URL to encode into the symbol.
PATCH /api/v1/codes/:id codes:write Change where a code points, rename it, or pause it.
POST /api/v1/codes/:id/archive codes:write Stop a code resolving. History is kept.
GET /api/v1/links links:read List short links.
POST /api/v1/links links:write Create a short link, optionally with a chosen ending.
GET /api/v1/analytics/codes/:id analytics:read Scans, unique visitors, daily series and countries.

A code comes back with these fields:

FieldWhat it is
idThe code's identifier, used in every path that names one.
nameYour own label for it.
modedynamic or static. Only a dynamic code can be repointed.
shortCodeThe ending of its short link.
urlThe address the symbol encodes, on your own domain if you have one.
destinationWhere it currently forwards to.
scansHow many times it has been scanned.
createdAtWhen it was made.

Repointing a code

The request most integrations exist to make.

Repoint a code
curl -X PATCH https://lynkarr.com/api/v1/codes/code_abc123 \
  -H "Authorization: Bearer lyn1_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/recall-notice"}'

The short link and the scan history are unchanged. Only the destination moves. A static code refuses this with 400, because its destination is encoded in the printed symbol and genuinely cannot change.

Creating a code

Create a QR code
curl -X POST https://lynkarr.com/api/v1/codes \
  -H "Authorization: Bearer lyn1_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{"name": "Batch 4471", "url": "https://example.com/batch/4471"}'

The response includes encode โ€” the value to render into the QR symbol. Rendering happens on your side or in our designer; the API stores the definition and owns the redirect.

Reading scans

Read a code's scans
curl "https://lynkarr.com/api/v1/analytics/codes/code_abc123?days=30" \
  -H "Authorization: Bearer lyn1_your_token_here"

Aggregated rather than raw: totals, unique visitors, a daily series and a country breakdown. Individual scan records are never returned, and no IP address is stored to return.

Errors

Every failure returns the same shape. Match on code, never on the sentence โ€” the wording will be improved, the code will not change.

An error
{
  "error": {
    "code": "forbidden",
    "message": "This token does not have the `codes:write` scope.",
    "docs": "https://lynkarr.com/docs/api"
  }
}
StatusCodeMeaning
400invalid_requestThe request was malformed or asked for something impossible.
401unauthorizedMissing, unknown, revoked or expired token.
402plan_requiredThe plan does not include this, or an allowance is used up.
403forbiddenThe token is valid but lacks the scope.
404not_foundNo such object for this company.
429rate_limitedToo many requests. Honour Retry-After.

A revoked token, an unknown token and one belonging to a suspended company all return the same 401. Distinguishing them would make this endpoint a way to test whether a guessed token exists.

Rate limit and quota

Two separate ceilings, because they fail for different reasons and are fixed in different ways.

60 on Starter, 120 on Business, 600 on EnterpriseRequests per minute, per token. Separate from your monthly allowance.

The per-minute limit, per token. Exceeding it returns 429 with Retry-After in seconds. This protects the platform rather than metering you โ€” wait a moment and continue.

The monthly allowance above, per company. Exhausting it returns 402 and quota_exceeded; waiting will not help until the month turns over.

Every response carries both, so an integration can pace itself rather than discovering a ceiling by hitting it: RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, and โ€” on metered plans โ€” Quota-Limit and Quota-Remaining.

Versioning

The version is in the path. /api/v1 will not change shape beneath you: fields may be added, but nothing that exists today will be removed or repurposed. A breaking change would arrive as /api/v2.

Create a token