The /v1 API lets a workspace create, list, retarget, pause, activate and delete hosted QR codes, read each code's scan stats, get each code's QR as a styled SVG or PNG, and read its plan usage. Every code gets a public scan URL at the domain root: https://vlcard.me/<short_code>. On plans with custom links (Business and above) a code can also have a vanity slug, https://vlcard.me/<slug>, which scans the same way; the short-code URL keeps working either way. Scans get a 302 to the code's current destination, so you can change where a printed QR goes without reprinting it.
On Enterprise and the partner API plans, webhooks push code changes and scans to your own HTTPS endpoint as they happen; see Webhooks.
Call the API from your server. Browser calls from other origins are blocked by CORS, and an API key in front-end code is a leaked key.
Requests and responses are JSON (Content-Type: application/json). Timestamps are RFC 3339 in UTC. Codes created through the API always have origin set to api.
Destination rules (checked on create and update, same rules as the dashboard):
http or https URL with a host, at most 2048 bytes after trimming surrounding whitespace.
No spaces or control characters inside the URL, no user@ userinfo, no IP-literal hosts such as [::1], and a port of 1 to 5 digits if present.
Percent escapes in the path and fragment must be valid and must not encode NUL, CR or LF. The query string is passed through as is.
A destination that breaks any rule is rejected with 400 invalid_destination.
Base URL: https://vlcard.me/v1
Authentication
A workspace API key, sent as X-API-Key: vlq_…. Managers of a workspace whose plan includes API access mint keys in the dashboard under API. The full key is shown once; only a hash is stored, so if you lose it, revoke it and mint a new one. A key acts on its own workspace only.
Rate limits
There are two budgets, chosen after the key is looked up.
Valid key: limited per key to your plan's requests per minute (Business 120, Enterprise 600, Partner 300, Scale 1,200, Platform 3,000). The window is a fixed minute that starts with the first request. Over the limit you get 429 rate_limited with no rate-limit headers; wait for the minute to pass.
Missing, unknown, revoked or no-access key: 60 requests per minute per client IP, shared by every protected /v1 route. These responses carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (seconds until the window resets). The 61st request gets 429 rate_limited with Retry-After in seconds.
GET /v1/health is never rate limited. Scans of https://vlcard.me/<short_code> never count against these limits and are never answered with 429.
Errors
Errors are JSON with one field, error, holding a stable snake_case code: {"error": "not_found"}. Branch on the code, not on the HTTP status alone. Unmatched paths under /v1 return 404 not_found.
Error codes
Code
Status
Meaning
missing_api_key
401
No X-API-Key header.
invalid_api_key
401
The key is unknown, mistyped or revoked.
api_access_required
403
The workspace's plan doesn't include API access.
rate_limited
429
The per-key or no-key IP budget is spent.
not_found
404
No such code in this workspace, a malformed short code, or an unknown /v1 path.
invalid_json
400
The body isn't a JSON object with the documented field types.
invalid_limit
400
limit isn't an integer of 1 or more.
invalid_offset
400
offset isn't an integer of 0 or more.
invalid_expiry
400
expires_at isn't an RFC 3339 timestamp.
invalid_name
400
name is neither a string nor null.
invalid_destination
400
The destination is missing or breaks the destination rules.
expiry_must_be_future
400
expires_at isn't in the future.
expiry_exceeds_plan_limit
400
expires_at is further out than the plan allows.
ads_not_available
400
has_ad is true on a plan without an ad-supported pool.
invalid_status
400
Reserved; not returned by the current endpoints.
active_limit_reached
403
The clean active pool is full.
ad_limit_reached
403
The ad-supported active pool is full.
library_limit_reached
403
The workspace holds as many codes as the plan allows.
redirect_quota_reached
403
This month's redirect units are used up.
code_expired
409
The code is past expires_at and can't be activated.
invalid_slug
400
vanity_slug isn't a valid slug (or isn't a string or null).
not_entitled
403
The plan doesn't include custom links (Business and above).
slug_taken
409
The slug is used by another code, or reads as an existing short code.
slug_cooling_down
409
Another workspace released the slug less than 90 days ago.
slug_reserved
422
The slug is a reserved word or blocked by staff.
managed_by_visionlink_card
409
The code belongs to a VisionLink digital card and can't get a custom link or style here.
legacy_code_read_only
409
The code is a legacy VisionLink code printed before v2. You can read it (get, list, stats, image) but not change, pause, delete, restyle or link it through the API.
invalid_date
400
from or to isn't a YYYY-MM-DD date.
invalid_range
400
from is after to, the range is longer than 366 days, or it ends before the oldest day the plan keeps.
analytics_not_available
403
The plan doesn't include scan stats over the API (Business and above).
invalid_format
400
format isn't svg or png.
invalid_size
400
size isn't a whole number from 512 to 2048.
invalid_preset
400
preset is missing, empty, or not a string or null.
preset_not_found
404
The preset isn't one of this workspace's presets, or there is no default preset.
presets_not_available
403
The plan doesn't include presets (Business and above).
preset_not_usable
409
The preset's logo was deleted or its frame text is no longer allowed. Fix it in the dashboard.
render_failed
502
Drawing the image failed. Safe to retry.
image_unavailable
503
Images are temporarily unavailable. Safe to retry later.
internal_error
500
Unexpected server error.
Codes
Hosted QR codes owned by the key's workspace.
GET/v1/codes
List codes
Returns the workspace's codes, newest first. The list includes codes created in the dashboard, not only API-created ones. total is the count of all codes in the workspace, so page with offset until you have seen total rows.
GET /v1/codes parameters
Field
Type
Description
limitquery
integer
Page size, 1 or more. Values above 100 are treated as 100.
Creates an active code with a new six-character short_code. The code counts against the plan's active pool (clean, or ad-supported when has_ad is true), library size and monthly redirect quota. Its scan URL is https://vlcard.me/<short_code>.
POST /v1/codes request body
Field
Type
Description
destinationrequired
string (uri)
http or https URL that follows the destination rules. Surrounding whitespace is trimmed. maxLength is in bytes.
name
string | null
Optional label. Trimmed; empty means no name.
expires_at
string (date-time) | null
Optional RFC 3339 timestamp in the future, within the plan's maximum expiry. null or an empty string means no expiry.
has_ad
boolean
Partner plans (Partner, Scale, Platform) only. Puts the code in the ad-supported pool, whose scans cost 0.25 redirect units. On other plans true returns 400 ads_not_available. Default false.
A deleted code (from the dashboard or the API) is not returned by the API (list or get); it answers 404 like a code that never existed.
GET /v1/codes/{code} parameters
Field
Type
Description
codepathrequired
string
The code's six-character short_code (not its id). Case-sensitive. Anything that isn't six letters or digits, or belongs to another workspace, returns 404 not_found.
Sets a new destination and optionally changes the name. Scans follow the new destination straight away. The short code, status and expiry don't change.
vanity_slug sets (string) or removes (null or empty string) the code's custom link, https://vlcard.me/<slug>. A request that only sets vanity_slug may leave out destination. Changes are all-or-nothing: if the slug is refused, the destination isn't changed either. Changing or removing a slug breaks anything printed with the old slug (the short-code URL keeps working); the old slug is held for 90 days so only this workspace can take it back.
PATCH /v1/codes/{code} parameters
Field
Type
Description
codepathrequired
string
The code's six-character short_code (not its id). Case-sensitive. Anything that isn't six letters or digits, or belongs to another workspace, returns 404 not_found.
PATCH /v1/codes/{code} request body
Field
Type
Description
destination
string (uri)
The new destination. Required on every update, even if only the name changes, unless the request only sets vanity_slug.
name
string | null
Leave the field out to keep the current name. Send a string to set it, or null or "" to remove it.
vanity_slug
string | null
Business plans and above. Leave out to keep the current custom link. A string sets it (3-32 characters of lowercase letters, digits and single dashes, not starting or ending with a dash; input is lowercased); null or "" removes it.
Deletes the code for good. The scan URL stops redirecting at once and shows a "no longer active" page (410), and the short code is never given to anyone else. A deleted code can't be restored through the API, is no longer returned by list, get or stats, and still counts toward your plan's library limit. Its custom link, if any, is released. To stop scans but keep the code, pause it instead.
DELETE /v1/codes/{code} parameters
Field
Type
Description
codepathrequired
string
The code's six-character short_code (not its id). Case-sensitive. Anything that isn't six letters or digits, or belongs to another workspace, returns 404 not_found.
Sets status to paused. Scans show an "unavailable" page instead of redirecting, and the code stops counting against the active pool. It stays in the library. No request body. Pausing an already paused code succeeds.
POST /v1/codes/{code}/pause parameters
Field
Type
Description
codepathrequired
string
The code's six-character short_code (not its id). Case-sensitive. Anything that isn't six letters or digits, or belongs to another workspace, returns 404 not_found.
Request
curl -s -X POST https://vlcard.me/v1/codes/aB3xY9/pause \
-H "X-API-Key: $VLQ_API_KEY"
Sets status to active so scans redirect again. Re-checks the plan's active pool for a paused code. A code past its expires_at can't be activated; create a new code instead. No request body.
POST /v1/codes/{code}/activate parameters
Field
Type
Description
codepathrequired
string
The code's six-character short_code (not its id). Case-sensitive. Anything that isn't six letters or digits, or belongs to another workspace, returns 404 not_found.
Request
curl -s -X POST https://vlcard.me/v1/codes/aB3xY9/activate \
-H "X-API-Key: $VLQ_API_KEY"
Scan counts for one code over a range of days: totals, one row per day and the top breakdowns. Available on Business and every plan above it (Business, Enterprise, Partner, Scale and Platform). Other plans get 403 analytics_not_available.
Days are calendar days in Africa/Johannesburg (SAST), and from and to are both included. Leave both out for the last 30 days up to today. A range can be at most 366 days. A to after today is treated as today. A from older than the plan keeps is moved up to the oldest day the plan keeps, and the response's from shows the day actually used. window_months is how far back the plan keeps scans (Business and Partner 12, Scale 24, null for unlimited on Enterprise and Platform).
scans and bot_scans count every scan, bots included. Bots are left out of unique_visitors, daily[].unique_visitors and every breakdown except devices. scans_lifetime and last_scanned_at cover the code's whole life and ignore the range. Only counts are returned, never personal data such as IP addresses or user agents.
GET /v1/codes/{code}/stats parameters
Field
Type
Description
codepathrequired
string
The code's six-character short_code (not its id). Case-sensitive. Anything that isn't six letters or digits, or belongs to another workspace, returns 404 not_found.
fromquery
string (date)
First day of the range, YYYY-MM-DD in SAST. Defaults to 29 days before to. Moved up to the plan's oldest kept day if it is older.
toquery
string (date)
Last day of the range, YYYY-MM-DD in SAST, included. Defaults to today. A day after today is treated as today.
The code's QR as an SVG or PNG, drawn exactly like a dashboard download: it always encodes the permanent https://vlcard.me/<short_code> (never a custom link), with a 4-module quiet zone, error correction M (H when the style has a logo), and the "Made with VisionLink QR" caption band when the code carries a watermark. Codes created through the API never do.
The style comes from your workspace's presets, which you build in the dashboard (Settings, QR designs). The API never takes raw style JSON, logos or frame text.
No preset: the code's own saved style, set in the dashboard or with PUT /v1/codes/{code}/style. A code without one is plain.
preset=default: the workspace's default preset (plain when there is none).
preset=<id>: that preset. Another workspace's preset, or an unknown id, is 404 preset_not_found.
On a plan without QR styling the image is plain, and the saved style is kept for when you upgrade. A preset's logo that has since been deleted, or frame text that is no longer allowed, is left out of the image.
The response carries a strong ETag that depends only on the drawing, and Cache-Control: private, no-cache. Store the image and send If-None-Match with its ETag; while nothing changed you get 304 with no body, which is cheap. Each request, 304 included, counts against your per-key rate limit.
GET /v1/codes/{code}/image parameters
Field
Type
Description
codepathrequired
string
The code's six-character short_code (not its id). Case-sensitive. Anything that isn't six letters or digits, or belongs to another workspace, returns 404 not_found.
formatquery
"svg" | "png"
svg (default) or png. Email signatures, Office and many website builders need PNG.
sizequery
integer
Width of the whole image in pixels, 512 to 2048 (default 1024). A frame or the watermark band makes the image taller than it is wide. SVG scales freely; the size only sets its width and height.
presetquery
string
default, or a preset id from the dashboard. Leave it out to use the code's own saved style.
Saves one of your workspace's presets onto the code, so the dashboard, its downloads and GET /v1/codes/{code}/image without a preset all draw it. null clears the style (plain). Available on Business and above; other plans get 403 presets_not_available (clearing works on any plan).
The preset's style is copied onto the code: editing the preset in the dashboard later doesn't change codes it was saved onto. A preset whose logo has since been deleted, or whose frame text is no longer allowed, is refused with 409 preset_not_usable; fix it in the dashboard first.
PUT /v1/codes/{code}/style parameters
Field
Type
Description
codepathrequired
string
The code's six-character short_code (not its id). Case-sensitive. Anything that isn't six letters or digits, or belongs to another workspace, returns 404 not_found.
A snapshot of the workspace's plan and how much of it is used. A null limit means unlimited. Redirect units reset each calendar month (Africa/Johannesburg); a clean scan costs 1 unit and an ad-supported scan 0.25. When over_quota is true, existing codes keep redirecting but creates fail with redirect_quota_reached.
Answers without touching the database. Use it for uptime checks, not to test your key.
No API key needed.
Request
curl -s https://vlcard.me/v1/health
200 The API process is running.
{
"status": "ok"
}
Webhooks
Webhooks push events to your own HTTPS endpoint as they happen, so you don't have to poll /v1. They come with Enterprise and the partner API plans (Partner, Scale, Platform).
Setting up. Workspace owners and admins add endpoints in the dashboard under Settings → Webhooks: an HTTPS URL and the events it should receive. A workspace can have up to 5 endpoints. Each endpoint gets its own signing secret (whsec_…), shown once when you add the endpoint or rotate the secret; keep it on your server like a password. Rotating replaces the secret at once, including for retries of earlier events. Send test event posts a webhook.test event to that endpoint only, once. Endpoints are managed in the dashboard only; there are no /v1 endpoints for them.
Events.
code.created: a code was created in the dashboard, over /v1 or by our staff. A code created with a custom link arrives once, with vanity_slug already set.
code.updated: a code's destination, name, status (paused, activated, expired) or expiry changed, or its custom link was set, changed or removed. data.changes lists what changed and data.previous holds the old values. A code becomes expired when the first scan after expires_at finds it, so that event arrives then, not at expires_at itself.
code.deleted: a code was deleted (retired). Its short code is never reused and scans get a "no longer active" page.
scan.created: codes were scanned. Scans are grouped: one event carries 1 to 100 scans (data.scans) of one workspace, gathered over about 2 seconds, so a busy code doesn't cause a request per scan. Each scan's code.vanity_slug is the custom link that scan came through, or null when the short-code URL was scanned.
Delivery. We POST a JSON body {id, type, created_at, workspace_id, data} with Content-Type: application/json, a few seconds after the event. Any 2xx within 10 seconds counts as delivered; redirects are not followed and count as a failure. Failures are retried with backoff (30 s, 2 min, 10 min, 30 min, 1 h, 2 h, 4 h, 8 h, 8 h), 10 attempts over about 24 hours, then the delivery is marked failed. An endpoint that has failed for 3 days without a single success is disabled; the dashboard shows it and you can enable it again. Every delivery from the last 30 days is listed under its endpoint with its status, response code and attempts, and can be sent again from there.
Order and duplicates. Events can arrive out of order and, rarely, more than once (delivery is at least once). Use id (evt_…) to drop duplicates, created_at or the code's updated_at to order them, and each scan's own id if you store scans. Answer quickly with a 2xx and do slow work afterwards.
Verifying. Every request carries VisionLink-Signature: t=<unix seconds>,v1=<hex>, where the hex is HMAC-SHA256 with your endpoint's secret (the whole whsec_… string as the key) over <t>.<raw request body>. Compute it over the raw bytes you received, before any JSON parsing, compare in constant time, and reject a t more than 5 minutes from your clock so an old request can't be replayed. There may be more than one v1= value; accept the request if any of them matches. VisionLink-Event-Id and VisionLink-Event-Type repeat the body's id and type.
Privacy. Scan events carry the time, country, device type, browser, operating system, referring site's domain, campaign (UTM) tags and whether the scan looked like a bot. Never the scanner's IP address (or its hash), user-agent text, language or visitor identifier.
Webhook request headers
Field
Type
Description
VisionLink-Signaturerequired
string
t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>" with the endpoint secret>. Reject a t more than 5 minutes from your clock.
VisionLink-Event-Idrequired
string
The event's id. The same on every retry and resend; use it to drop duplicates.
VisionLink-Event-Typerequired
string
The event's type.
POSTcode.created
A code was created
Sent to endpoints subscribed to code.created when a code is created in the dashboard, over /v1 or by staff. A code created with a custom link arrives once, with vanity_slug set.
Sent when a code's destination, name, status or expiry changes, or its custom link is set, changed or removed. changes lists the fields that changed; previous holds their old values.
Sent when a code is deleted (retired). The code keeps its short code forever; status is deleted, its custom link is released and scans get a "no longer active" page.
Sent a few seconds after scans. One event carries 1 to 100 scans of one workspace, gathered over about 2 seconds; a busy workspace gets several events. Each scan has its own id for de-duplication, and code.vanity_slug is the custom link used for that scan (null when the short code was scanned), even if the code's link has changed since. Counts-level fields only; never the scanner's IP address, its hash, the user-agent text or a visitor identifier.
Sent once, only to the endpoint you pressed Send test event for, whatever events it subscribes to. It can't be subscribed to and is never retried. Use it to check your URL and your signature check.
Body
{
"id": "evt_c0ffee00c0ffee00c0ffee00c0ffee00",
"type": "webhook.test",
"created_at": "2026-09-23T08:05:00.000Z",
"workspace_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"data": {
"message": "Test event from VisionLink QR. Your endpoint received and can verify it.",
"endpoint_id": "9b2e7c1a-4d3f-4a6b-8c9d-0e1f2a3b4c5d"
}
}
Verifying the signature
Node.js
// Node 18+. Keep the raw body: with Express, use express.raw({ type: "application/json" }).
import crypto from "node:crypto";
export function verifyVisionLinkSignature(rawBody, header, secret, toleranceSeconds = 300) {
let timestamp = NaN;
const signatures = [];
for (const piece of String(header ?? "").split(",")) {
const [key, value] = piece.trim().split("=");
if (key === "t") timestamp = Number(value);
if (key === "v1" && value) signatures.push(value);
}
if (!Number.isInteger(timestamp) || signatures.length === 0) return false;
if (Math.abs(Math.floor(Date.now() / 1000) - timestamp) > toleranceSeconds) return false;
const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.`).update(rawBody).digest();
return signatures.some((sig) => {
const given = Buffer.from(sig, "hex");
return given.length === expected.length && crypto.timingSafeEqual(given, expected);
});
}
// app.post("/visionlink/webhooks", express.raw({ type: "application/json" }), (req, res) => {
// const ok = verifyVisionLinkSignature(req.body, req.get("VisionLink-Signature"), process.env.VISIONLINK_WEBHOOK_SECRET);
// if (!ok) return res.sendStatus(400);
// const event = JSON.parse(req.body);
// // Drop duplicates by event.id, then handle event.type.
// res.sendStatus(204);
// });
Go
package webhook
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"errors"
"strconv"
"strings"
"time"
)
// VerifySignature checks a VisionLink-Signature header against the raw request body.
func VerifySignature(body []byte, header, secret string, tolerance time.Duration) error {
timestamp := int64(-1)
var signatures []string
for _, part := range strings.Split(header, ",") {
key, value, _ := strings.Cut(strings.TrimSpace(part), "=")
switch key {
case "t":
n, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return errors.New("bad timestamp")
}
timestamp = n
case "v1":
signatures = append(signatures, value)
}
}
if timestamp < 0 || len(signatures) == 0 {
return errors.New("no signature")
}
if age := time.Since(time.Unix(timestamp, 0)); age > tolerance || age < -tolerance {
return errors.New("timestamp outside the tolerance")
}
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(strconv.FormatInt(timestamp, 10) + "."))
mac.Write(body)
expected := mac.Sum(nil)
for _, s := range signatures {
if given, err := hex.DecodeString(s); err == nil && hmac.Equal(given, expected) {
return nil
}
}
return errors.New("signature mismatch")
}
// In your handler: read the raw body, then
// err := VerifySignature(body, r.Header.Get("VisionLink-Signature"), secret, 5*time.Minute)
// Answer 400 on an error; otherwise drop duplicates by the event id, handle it and answer 204.
Objects
QRCode
QRCode fields
Field
Type
Description
idrequired
string (uuid)
Internal id. Use short_code in API paths.
org_idrequired
string (uuid)
The workspace that owns the code.
short_coderequired
string
Six case-sensitive letters and digits. The scan URL is https://vlcard.me/<short_code>.
namerequired
string | null
Your label for the code. Never shown to scanners.
destinationrequired
string (uri)
Where scans are sent, stored trimmed. maxLength is in bytes.
statusrequired
"active" | "paused" | "expired"
active redirects. paused and expired show an unavailable page. A code becomes expired once a scan finds it past expires_at.
How the code was created. api for this API; the others are dashboard origins. legacy is a code carried over unchanged from the previous VisionLink QR system (printed as https://qr.visionlink.co.za/qr/<code>); only VisionLink's own workspace has them.
expires_atrequired
string (date-time) | null
After this moment scans stop redirecting. null means no expiry.
has_adrequired
boolean
Whether the code is in the ad-supported pool.
created_atrequired
string (date-time)
updated_atrequired
string (date-time)
vanity_slugrequired
string | null
The code's custom link slug, lowercase. null when unset.
vanity_urlrequired
string (uri) | null
https://vlcard.me/<vanity_slug>, or null when unset. Scans the same as the short-code URL.
CodeList
CodeList fields
Field
Type
Description
codesrequired
QRCode[]
totalrequired
integer
All codes in the workspace, not just this page.
CodeStats
CodeStats fields
Field
Type
Description
short_coderequired
string
The code the stats are for.
fromrequired
string (date)
First day counted (SAST). Later than the from you sent if the plan doesn't keep scans that old.
torequired
string (date)
Last day counted (SAST), included. Never after today.
timezonerequired
"Africa/Johannesburg"
The time zone the days are counted in.
window_monthsrequired
integer | null
How many months of scans the plan keeps. null is unlimited.
scansrequired
integer
Scans in the range, bots included.
unique_visitorsrequired
integer
Distinct visitors in the range, bots left out. A visitor is an anonymous hash, never returned.
bot_scansrequired
integer
Scans in the range that came from bots. Already counted in scans.
scans_lifetimerequired
integer
Every scan the code has ever had, bots included. Ignores the range and the plan's window.
last_scanned_atrequired
string (date-time) | null
The code's most recent scan, whatever the range. null if it has never been scanned.
dailyrequired
StatsDaily[]
One row per day from from to to, oldest first. Days without scans are included with zeros.
countriesrequired
StatsBreakdownItem[]
Top 20 countries by scans, as two-letter ISO codes such as ZA. Bots and scans with no known country are left out. Countries come from the DB-IP IP to Country Lite database (CC BY 4.0), so wherever you show them, credit it with the link "IP Geolocation by DB-IP" pointing to db-ip.com.
devicesrequired
StatsBreakdownItem[]
Scans by device type (mobile, tablet, desktop, bot, unknown). The only breakdown that includes bots.
browsersrequired
StatsBreakdownItem[]
Top 20 browsers by scans, bots left out. Unknown when the browser couldn't be told.
operating_systemsrequired
StatsBreakdownItem[]
Top 20 operating systems by scans, bots left out. Unknown when the system couldn't be told.
referrersrequired
StatsBreakdownItem[]
Top 20 referring hosts by scans, bots left out. Direct when the scan had no referrer, which is usual for a camera scan.
utm_sourcesrequired
StatsBreakdownItem[]
Top 20 utm_source values on the scan URL by scans, bots left out. Scans without one are left out.
StatsDaily
StatsDaily fields
Field
Type
Description
dayrequired
string (date)
A calendar day in SAST.
scansrequired
integer
Scans that day, bots included.
unique_visitorsrequired
integer
Distinct visitors that day, bots left out.
StatsBreakdownItem
StatsBreakdownItem fields
Field
Type
Description
keyrequired
string
The value being counted, for example ZA, mobile or Chrome.
scansrequired
integer
Scans with this value in the range. Lists are sorted by scans, highest first, then by key. An empty list is [].
Usage
Usage fields
Field
Type
Description
audiencerequired
"b2b" | "b2c"
b2b for partner plans, b2c for Business and Enterprise.
api_accessrequired
boolean
plan_idrequired
string
Plan id, for example partner, scale, pro (Business) or enterprise.
display_namerequired
string
clean_activerequired
integer
Active codes in the clean pool.
clean_limitrequired
integer | null
Clean active cap. null is unlimited.
ad_activerequired
integer
Active codes in the ad-supported pool.
ad_limitrequired
integer | null
Ad-supported active cap. null is unlimited.
library_usedrequired
integer
Codes stored in the workspace, active or not.
library_limitrequired
integer | null
Library cap. null is unlimited.
redirect_unitsrequired
number
Redirect units used this month.
redirect_limitrequired
integer | null
Monthly redirect units. null is unlimited.
over_quotarequired
boolean
True when redirect_units has reached redirect_limit. Creates are blocked; scans still redirect.
WebhookEvent
WebhookEvent fields
Field
Type
Description
idrequired
string
Unique event id. The same on every retry and resend; use it to drop duplicates.