QRdx

REST API and OAuth

Manage dynamic QR codes, read scan analytics, report conversions and subscribe to webhooks over HTTP with OAuth 2.0 access tokens.

The QRdx REST API lives under https://api.qrdx.dev/v1. It uses JSON and, apart from the keyless image API, authenticates requests with an OAuth 2.0 access token:

curl https://api.qrdx.dev/v1/codes -H "Authorization: Bearer $QRDX_TOKEN"

Requests made with a token act on the token owner's personal workspace. The codes, conversions and hooks endpoints also accept the browser session of someone signed in to QRdx; those requests act on the open team.

The same endpoints also answer under https://qrdx.dev/api/v1. Browser-session requests use that path, since the sign-in cookie belongs to qrdx.dev, and a self-hosted instance serves the API at /api/v1 on its own domain.

Endpoints

EndpointScopeWhat it does
GET /v1/qrNoneQR code image as SVG, PNG or EPS. See Image API
/v1/codescodes:read, codes:writeList, create (one or up to 100 at a time), update and delete dynamic codes. See Dynamic QR codes
GET /v1/codes/{id}/scanscodes:readScan analytics for a code, or individual scans page by page
POST /v1/conversionscodes:writeAttribute a sale or sign-up to the scan that led to it (Business). See Tracking and conversions
/v1/hookscodes:read, codes:writeSubscribe a URL to events, REST Hooks style, for Zapier, Make and n8n. See Webhooks
GET /v1/themes, GET /v1/themes/{id}themes:readYour saved QR themes (name and style)
GET /v1/meprofile:readThe signed-in user's id, name, email and avatar

codes:write also allows everything codes:read does.

Get an access token

QRdx is an OAuth 2.0 provider. Your app sends people to QRdx to sign in, and gets back an access token that can only do what the granted scopes allow.

ScopeAllows
profile:readRead the user's name, email and avatar
themes:readRead the user's saved QR themes
codes:readRead dynamic codes and their scan analytics
codes:writeCreate, edit and delete dynamic codes, report conversions, manage webhook subscriptions

Register an app

Create an OAuth app yourself in Settings → Developers: give it a name, its redirect URIs and the scopes it needs, and you get a client ID and a client secret. The secret is shown once; keep it on your server. Free workspaces can have 1 app, Pro 5 and Business 25. Build an integration walks through the whole flow, from creating the app to getting it listed in the integrations directory.

On a self-hosted instance you can also create a first-party app from apps/docs:

pnpm exec tsx scripts/create-oauth-app.ts \
  --name "My app" \
  --redirect-uris "https://myapp.example/callback" \
  --scopes "codes:read,codes:write"

Send the user to QRdx

https://qrdx.dev/api/oauth/authorize
  ?response_type=code
  &client_id=<client id>
  &redirect_uri=https://myapp.example/callback
  &scope=codes:read codes:write
  &state=<random value>
  &code_challenge=<PKCE challenge>
  &code_challenge_method=S256

redirect_uri must exactly match a registered URL, and scope (space or comma separated) may only ask for the app's scopes. PKCE is recommended, and required for apps that turn on Require PKCE; S256 is the default method. People sign in if needed, then approve your app on the QRdx consent screen, which shows its name, logo, website, who built it and the requested permissions. QRdx then redirects to redirect_uri with code and your state, or with error=access_denied if they cancel. The code is valid for 10 minutes and can be used once.

Exchange the code for tokens

curl -X POST https://qrdx.dev/api/oauth/token \
  -d grant_type=authorization_code \
  -d client_id=$CLIENT_ID \
  -d client_secret=$CLIENT_SECRET \
  -d code=$CODE \
  -d redirect_uri=https://myapp.example/callback \
  -d code_verifier=$CODE_VERIFIER
{
  "access_token": "...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "...",
  "scope": "codes:read codes:write"
}

The token endpoint takes a form-encoded body. Access tokens last 1 hour and refresh tokens 30 days.

Refresh and revoke

# New access and refresh tokens; the old refresh token stops working
curl -X POST https://qrdx.dev/api/oauth/token \
  -d grant_type=refresh_token \
  -d client_id=$CLIENT_ID \
  -d client_secret=$CLIENT_SECRET \
  -d refresh_token=$REFRESH_TOKEN

# Revoke an access or refresh token
curl -X POST https://qrdx.dev/api/oauth/revoke -d token=$TOKEN

GET /api/oauth/userinfo returns the user as sub, name, email and picture for tokens with profile:read.

People can revoke an app's access themselves in Settings → Authorized apps. Its tokens for that account then fail with invalid_token (API calls) and invalid_grant (refresh), and the app has to ask again.

Errors and limits

The codes, conversions and hooks endpoints return errors as { "code": "...", "message": "...", "status": 400 }; the status codes are listed under Dynamic QR codes. The OAuth, themes and profile endpoints use the OAuth shape, { "error": "invalid_token", "error_description": "..." }.

Requests are rate limited, and a 429 response tells you when to retry. The codes API allows 120 reads and 30 writes a minute per user. Creating several codes in one request and moving codes onto a custom domain need Pro or Business (402 PLAN_REQUIRED otherwise). Scans are never limited.

Last updated on

On this page