API documentation
Generate branded QR codes at scale over a simple REST API. All endpoints are versioned under /api/v1 and return JSON.
All requests require a Bearer token API key in the Authorization header. Create and manage keys in your dashboard under /dashboard/api-keys. Keys are shown once at creation, so store them securely.
Authorization: Bearer qrop_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keys are created in your dashboard. API access requires an active API plan; see the pricing page for available plans.
Errors return a JSON body of the form { "error": "..." } with an appropriate HTTP status.
| 401 | Missing or invalid API key. |
| 402 | Credits exhausted or no active subscription. |
| 400 | Malformed request (e.g. batch outside 1–25 items). |
| 422 | Invalid data type, format, resolution, logo, or colours with insufficient contrast to stay scannable. |
| 429 | Per-second burst or per-minute sustained rate limit exceeded. See the Retry-After header for when to retry. |
Each API key is limited independently per plan. Both windows are enforced in parallel, so a 429 fires if either is exceeded. Check the Retry-After header for the reset time.
| Plan | Req / sec | Req / min | Max resolution |
|---|---|---|---|
| Starter | 5 | 100 | 1 024px |
| Pro | 15 | 400 | 2 048px |
| Growth | 25 | 1 000 | 2 048px |
| Enterprise | 100 | 5 000 | 4 096px |
Generate a single QR code. Consumes 1 credit.
| Field | Type | Description | |
|---|---|---|---|
| data | string | required | Content to encode (URL, text, vCard string, etc.). |
| type | string | required | One of: url, text, vcard, wifi, email, sms, phone, geo. |
| format | string | required | png, svg, or pdf. |
| resolution | number | required | Square size in px, 1–4096. Plan caps: 1024px Starter · 2048px Pro/Growth · 4096px Enterprise. Returns 422 if exceeded. |
| foregroundColor | string | optional | Hex colour, default #000000. |
| backgroundColor | string | optional | Hex colour, default #FFFFFF. |
| finderColor | string | optional | Hex colour for the finder (corner) patterns. |
| logoUrl | string | optional | Fetched server-side, max 2MB, PNG/JPEG/WebP only. Forces error correction to H. |
| logoDataUrl | string | optional | Inline base64 image (data:image/png;base64,..., jpeg, or webp), max 2MB, PNG/JPEG/WebP only. Use this to upload a logo directly instead of hosting it at a fetchable URL. Takes precedence over logoUrl if both are sent. |
| errorCorrection | string | optional | L, M, Q, or H. Auto-upgraded to H when a logo is present. |
| moduleShape | string | optional | square (default), dots, or rounded: shape of the data modules. |
| finderShape | string | optional | square (default), rounded, or circle: shape of the three finder (corner) patterns. |
| imageRoundness | number | optional | Outer corner radius of the whole QR image as a fraction of its resolution (0–0.5, default 0). |
Request
{
"data": "https://example.com",
"type": "url",
"format": "png",
"resolution": 1024,
"foregroundColor": "#000000",
"backgroundColor": "#FFFFFF"
}Response 200
{
"id": "gen_a1b2c3",
"image": "data:image/png;base64,iVBORw0KG...",
"format": "png",
"resolution": 1024,
"creditsConsumed": 1
}Example request
curl -X POST https://www.qrop.co.za/api/v1/generate \ -H "Authorization: Bearer qrop_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "data": "https://example.com", "type": "url", "format": "png", "resolution": 1024 }'
Generate up to 25 QR codes in one request. Each item consumes 1 credit; credits are reserved for the full batch up front (no partial processing).
| Field | Type | Description | |
|---|---|---|---|
| items | array | required | 1–25 items, each with data and type (see /api/v1/generate). |
| format | string | required | png, svg, or pdf: applies to every item in the batch. |
| resolution | number | required | Square size in px, 1–4096: applies to every item. Same plan caps as /api/v1/generate. |
| logoUrl | string | optional | Fetched once and applied to every item in the batch, max 2MB, PNG/JPEG/WebP only. Not supported with svg format. |
| logoDataUrl | string | optional | Inline base64 image, same logo applied to every item. Takes precedence over logoUrl if both are sent. |
The batch logo is per-request, not per-item. Use separate batch calls (or /api/v1/generate) if items need different logos.
Request
{
"items": [
{ "data": "https://example.com/1", "type": "url" },
{ "data": "https://example.com/2", "type": "url" }
],
"format": "png",
"resolution": 512,
"logoUrl": "https://example.com/company-logo.png"
}Response 200
{
"results": [
{ "id": "gen_x1_0", "image": "data:image/png;base64,...", "success": true },
{ "id": "gen_x2_1", "image": "data:image/png;base64,...", "success": true }
],
"creditsConsumed": 2,
"failedCount": 0
}Example request
curl -X POST https://www.qrop.co.za/api/v1/generate/batch \ -H "Authorization: Bearer qrop_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "items": [ { "data": "https://example.com/1", "type": "url" }, { "data": "https://example.com/2", "type": "url" } ], "format": "png", "resolution": 512 }'
A batch with 0 or more than 25 items returns 400.
Generating large volumes? Items in a batch are rendered one at a time server-side, so a bigger batch size wouldn't generate any faster; it would just mean a slower call and a larger response body. For volumes beyond one batch, issue multiple 25-item batch calls in parallel from your client instead, staying within your plan's rate limit (see /api/v1/usage and the Rate limits section above).
Return current period usage, remaining allocation, carried credits from previous periods, and your rate limits.
Response 200
{
"plan": "growth",
"currentPeriodStart": "2026-06-01T00:00:00Z",
"currentPeriodEnd": "2026-07-01T00:00:00Z",
"includedCredits": 50000,
"includedCreditsUsed": 12450,
"carriedCredits": 8200,
"overageCredits": 0,
"overageCostZar": 0,
"rateLimit": { "requestsPerSecond": 25, "requestsPerMinute": 1000 }
}Example request
curl https://www.qrop.co.za/api/v1/usage \ -H "Authorization: Bearer qrop_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Rotate the calling API key. A new key is returned (shown once); the old key keeps working for a 24-hour grace period before it stops.
Response 200
{
"newKey": "qrop_live_yyyyyyyyyyyyyyyyyyyy",
"oldKeyValidUntil": "2026-06-25T10:00:00Z"
}Example request
curl -X POST https://www.qrop.co.za/api/v1/keys/rotate \ -H "Authorization: Bearer qrop_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Point a QR code at a Qrop-owned redirect URL instead of the destination directly, so scans get logged and the destination stays editable after printing. Registered-only, one extra credit per code. In development, not yet available on your account. Check back or watch the tracking guide for details on how it will work.
Why am I getting a 402 error?
A 402 means your API key has no active plan, or your included credits, free allocation, and purchased balance are all exhausted for the current period. Check /api/v1/usage for your current standing, or upgrade your plan on the pricing page.
How do I raise my rate limit?
Rate limits are tied to your API plan, see the Rate limits table above for the per-second and per-minute caps on each tier. Upgrading to a higher plan raises both limits immediately; there is no separate rate limit purchase.
Why did my request return a 422 instead of generating a QR code?
422 means the request was understood but rejected before any credit was consumed, usually an invalid data type or format, a resolution above your plan's cap, or a foreground/background colour combination with too little contrast to scan reliably. The error message states the specific reason.
Can I use the same API key for the web dashboard and the API?
API keys are for the REST API only, they authenticate requests to /api/v1/*. The web dashboard at qrop.co.za uses your regular account login, not an API key.
What happens to in-flight requests when I rotate a key?
The old key keeps working for a 24-hour grace period after rotation, so requests already using it won't break immediately. Update your integration to the new key within that window before the old one stops authenticating.