REST API
API reference
Base URL: https://api.qrhero.com/v1.
Authenticate with Authorization: Bearer <token>
and Accept: application/json.
All requests are scoped to the token's organization.
Machine-readable spec:
https://docs.qrhero.com/api/openapi.json
(OpenAPI 3.1 with typed schemas). See also
token abilities.
Status
/v1/status
status.read
Health check and token context
Returns API version, organization context, plan API limits, and the current token metadata.
- Ability
- Any valid token on an API-enabled plan
Example response
{
"status": "ok",
"version": "v1",
"organization": {
"ulid": "01HXYZORGULID000000000001",
"name": "Acme Marketing",
"slug": "acme-marketing"
},
"plan": {
"code": "professional",
"name": "Professional (annual)"
},
"api": {
"rate_limit_per_min": 120,
"calls_included_month": 50000,
"calls_used_month": 1240
},
"token": {
"name": "CI automation",
"abilities": [
"codes.view",
"codes.create",
"mcp.access"
]
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
status |
string | required | — |
version |
string | required | — |
organization |
object | required | — |
plan |
ref | null | optional | — |
api |
object | required | — |
token |
object | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/status" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/status', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/status'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/status', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/status");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
Organization
/v1/organization
organization.read
Read organization profile
Returns safe organization fields (name, locale, currency, plan). Billing identifiers are excluded.
- Ability
- Any valid token on an API-enabled plan
Example response
{
"data": {
"ulid": "01HXYZORGULID000000000001",
"name": "Acme Marketing",
"slug": "acme-marketing",
"locale": "en",
"currency": "EUR",
"plan": {
"code": "professional",
"name": "Professional (annual)"
},
"created_at": "2026-01-15T10:00:00+00:00",
"updated_at": "2026-07-01T08:30:00+00:00"
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
Organization | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/organization" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/organization', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/organization'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/organization', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/organization");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
Analytics
/v1/analytics
analytics.read
Read scan analytics
Hierarchical analytics payload for the organization, a brand, or a single code.
- Ability
-
analytics.view
Query parameters
range— 7, 30, or 90 (days, default 30)dimension— country | device | referrer | languagebrand_ulid— Optional brand scopecode_ulid— Optional code scope
Example response
{
"data": {
"scope_level": "organization",
"range_days": 30,
"totals": {
"scans": 1240,
"uniques": 890,
"unique_rate": 0.718
},
"time_series": [
{
"date": "2026-06-07",
"scans": 42
},
{
"date": "2026-06-08",
"scans": 38
}
],
"dimension": "country",
"dimension_label": "Country",
"dimension_breakdown": [
{
"label": "DK",
"scans": 520,
"uniques": 410
},
{
"label": "DE",
"scans": 310,
"uniques": 240
}
],
"child_breakdown": [
{
"key": "01HXYZCODEULID000000000001",
"label": "Launch 2026",
"scans": 620,
"uniques": 480
}
]
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
AnalyticsPayload | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/analytics?range=30&dimension=country&brand_ulid=01HXYZBRANDULID00000000001&code_ulid=01HXYZCODEULID000000000001" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/analytics?range=30&dimension=country&brand_ulid=01HXYZBRANDULID00000000001&code_ulid=01HXYZCODEULID000000000001', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/analytics?range=30&dimension=country&brand_ulid=01HXYZBRANDULID00000000001&code_ulid=01HXYZCODEULID000000000001'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/analytics?range=30&dimension=country&brand_ulid=01HXYZBRANDULID00000000001&code_ulid=01HXYZCODEULID000000000001', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/analytics?range=30&dimension=country&brand_ulid=01HXYZBRANDULID00000000001&code_ulid=01HXYZCODEULID000000000001");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/analytics/export
analytics.export
Export analytics payload
Same scope filters as analytics read, plus csv_rows for programmatic export.
- Ability
-
analytics.export
Query parameters
range— 7, 30, or 90 (days, default 30)dimension— country | device | referrer | languagebrand_ulid— Optional brand scopecode_ulid— Optional code scope
Example response
{
"data": {
"scope_level": "organization",
"range_days": 30,
"totals": {
"scans": 1240,
"uniques": 890,
"unique_rate": 0.718
},
"time_series": [
{
"date": "2026-06-07",
"scans": 42
},
{
"date": "2026-06-08",
"scans": 38
}
],
"dimension": "country",
"dimension_label": "Country",
"dimension_breakdown": [
{
"label": "DK",
"scans": 520,
"uniques": 410
},
{
"label": "DE",
"scans": 310,
"uniques": 240
}
],
"child_breakdown": [
{
"key": "01HXYZCODEULID000000000001",
"label": "Launch 2026",
"scans": 620,
"uniques": 480
}
],
"csv_rows": [
{
"date": "2026-06-07",
"country": "DK",
"scans": 42
}
]
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
AnalyticsPayload | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/analytics/export?range=30&dimension=country&brand_ulid=01HXYZBRANDULID00000000001&code_ulid=01HXYZCODEULID000000000001" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/analytics/export?range=30&dimension=country&brand_ulid=01HXYZBRANDULID00000000001&code_ulid=01HXYZCODEULID000000000001', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/analytics/export?range=30&dimension=country&brand_ulid=01HXYZBRANDULID00000000001&code_ulid=01HXYZCODEULID000000000001'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/analytics/export?range=30&dimension=country&brand_ulid=01HXYZBRANDULID00000000001&code_ulid=01HXYZCODEULID000000000001', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/analytics/export?range=30&dimension=country&brand_ulid=01HXYZBRANDULID00000000001&code_ulid=01HXYZCODEULID000000000001");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/analytics/qr-codes/{code_ulid}
analytics.qr_code.read
Read QR code rollup analytics
Per-code scan analytics from the qr_code_scan_daily rollup table.
- Ability
-
analytics.view
Query parameters
range— 7, 30, or 90 (days, default 30)dimension— country | device | referrer | language | provider
Example response
{
"data": {
"qr_code": {
"ulid": "01HXYZCODEULID000000000001",
"name": "Launch 2026",
"slug": "acme-marketing/launch-2026"
},
"range_days": 30,
"totals": {
"scans": 620,
"uniques": 480,
"unique_rate": 0.774
},
"time_series": [
{
"date": "2026-06-07",
"scans": 22
}
],
"dimension": "country",
"dimension_label": "Country",
"dimension_breakdown": [
{
"label": "DK",
"scans": 320,
"uniques": 260
}
]
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
QrCodeAnalyticsPayload | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/analytics/qr-codes/01HXYZCODEULID000000000001?range=30&dimension=country" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/analytics/qr-codes/01HXYZCODEULID000000000001?range=30&dimension=country', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/analytics/qr-codes/01HXYZCODEULID000000000001?range=30&dimension=country'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/analytics/qr-codes/01HXYZCODEULID000000000001?range=30&dimension=country', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/analytics/qr-codes/01HXYZCODEULID000000000001?range=30&dimension=country");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/analytics/qr-codes/{code_ulid}/raw-export
analytics.raw_export
Export raw scan rows for a QR code
Paginated raw qr_code_scans rows. Uses a separate, stricter per-minute rate limit.
- Ability
-
analytics.export
Query parameters
range— 7, 30, or 90 (days, default 30)limit— Page size (default 1000, max 5000)offset— Row offset for pagination (default 0)
Example response
{
"data": {
"qr_code": {
"ulid": "01HXYZCODEULID000000000001",
"slug": "acme-marketing/launch-2026"
},
"rows": [
{
"scanned_at": "2026-07-01T08:00:00+00:00",
"country": "DK",
"device_type": "mobile",
"referrer": "https://google.com"
}
],
"meta": {
"count": 1,
"limit": 1000,
"offset": 0,
"has_more": false
}
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
RawExportPayload | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/analytics/qr-codes/01HXYZCODEULID000000000001/raw-export?range=30&limit=1000&offset=0" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/analytics/qr-codes/01HXYZCODEULID000000000001/raw-export?range=30&limit=1000&offset=0', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/analytics/qr-codes/01HXYZCODEULID000000000001/raw-export?range=30&limit=1000&offset=0'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/analytics/qr-codes/01HXYZCODEULID000000000001/raw-export?range=30&limit=1000&offset=0', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/analytics/qr-codes/01HXYZCODEULID000000000001/raw-export?range=30&limit=1000&offset=0");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
Brands
/v1/brands
brands.list
List brands
Returns all brands in the token organization, including brand kit and settings metadata.
- Ability
-
brands.view
Example response
{
"data": [
{
"ulid": "01HXYZBRANDULID00000000001",
"name": "Summer Campaign",
"slug": "summer-campaign",
"brand_kit": {
"primary_color": "#0f3460",
"secondary_color": "#e94560"
},
"settings": {
"locale": "en"
},
"primary_domain": {
"ulid": "01HXYZDOMAINULID0000000001",
"host": "links.example.com"
},
"created_at": "2026-02-01T12:00:00+00:00",
"updated_at": "2026-07-01T08:30:00+00:00"
}
]
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
array<mixed> | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/brands" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/brands', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/brands'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/brands', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/brands");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/brands
brands.create
Create a brand
- Ability
-
brands.manage
Request body schema
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | required | required string |
slug |
string | optional | optional alpha_dash |
brand_kit |
object | optional | optional object |
settings |
object | optional | optional object |
primary_domain_ulid |
string | optional | optional ULID |
Example response
{
"data": {
"ulid": "01HXYZBRANDULID00000000001",
"name": "Summer Campaign",
"slug": "summer-campaign",
"brand_kit": {
"primary_color": "#0f3460",
"secondary_color": "#e94560"
},
"settings": {
"locale": "en"
},
"primary_domain": {
"ulid": "01HXYZDOMAINULID0000000001",
"host": "links.example.com"
},
"created_at": "2026-02-01T12:00:00+00:00",
"updated_at": "2026-07-01T08:30:00+00:00"
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
Brand | required | — |
Code samples
curl -sS -X POST "https://api.qrhero.com/v1/brands" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"name": "Automation token",
"slug": "launch-2026",
"brand_kit": {
"primary_color": "#4f46e5"
},
"settings": {
"locale": "en"
},
"primary_domain_ulid": "01HXYZDOMAINULID0000000001"
}'
const response = await fetch('https://api.qrhero.com/v1/brands', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Automation token",
"slug": "launch-2026",
"brand_kit": {
"primary_color": "#4f46e5"
},
"settings": {
"locale": "en"
},
"primary_domain_ulid": "01HXYZDOMAINULID0000000001"
}),
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/brands'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
'Content-Type': 'application/json',
}
payload = {
"name": "Automation token",
"slug": "launch-2026",
"brand_kit": {
"primary_color": "#4f46e5"
},
"settings": {
"locale": "en"
},
"primary_domain_ulid": "01HXYZDOMAINULID0000000001"
}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.qrhero.com/v1/brands', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'json' => {
"name": "Automation token",
"slug": "launch-2026",
"brand_kit": {
"primary_color": "#4f46e5"
},
"settings": {
"locale": "en"
},
"primary_domain_ulid": "01HXYZDOMAINULID0000000001"
},
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(
'{"name":"Automation token","slug":"launch-2026","brand_kit":{"primary_color":"#4f46e5"},"settings":{"locale":"en"},"primary_domain_ulid":"01HXYZDOMAINULID0000000001"}',
Encoding.UTF8,
"application/json");
var response = await client.POSTAsync("https://api.qrhero.com/v1/brands", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/brands/{brand_ulid}
brands.update
Update a brand
Partial update of brand fields. Omitted keys are left unchanged.
- Ability
-
brands.manage
Request body schema
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | optional | optional string |
slug |
string | optional | optional alpha_dash |
brand_kit |
object | optional | optional object |
settings |
object | optional | optional object |
primary_domain_ulid |
string | optional | optional ULID |
Example response
{
"data": {
"ulid": "01HXYZBRANDULID00000000001",
"name": "Summer Campaign",
"slug": "summer-campaign",
"brand_kit": {
"primary_color": "#0f3460",
"secondary_color": "#e94560"
},
"settings": {
"locale": "en"
},
"primary_domain": {
"ulid": "01HXYZDOMAINULID0000000001",
"host": "links.example.com"
},
"created_at": "2026-02-01T12:00:00+00:00",
"updated_at": "2026-07-01T08:30:00+00:00"
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
Brand | required | — |
Code samples
curl -sS -X PATCH "https://api.qrhero.com/v1/brands/01HXYZBRANDULID00000000001" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"name": "Automation token",
"slug": "launch-2026",
"brand_kit": {
"primary_color": "#4f46e5"
},
"settings": {
"locale": "en"
},
"primary_domain_ulid": "01HXYZDOMAINULID0000000001"
}'
const response = await fetch('https://api.qrhero.com/v1/brands/01HXYZBRANDULID00000000001', {
method: 'PATCH',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Automation token",
"slug": "launch-2026",
"brand_kit": {
"primary_color": "#4f46e5"
},
"settings": {
"locale": "en"
},
"primary_domain_ulid": "01HXYZDOMAINULID0000000001"
}),
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/brands/01HXYZBRANDULID00000000001'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
'Content-Type': 'application/json',
}
payload = {
"name": "Automation token",
"slug": "launch-2026",
"brand_kit": {
"primary_color": "#4f46e5"
},
"settings": {
"locale": "en"
},
"primary_domain_ulid": "01HXYZDOMAINULID0000000001"
}
response = requests.patch(url, headers=headers, json=payload)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('PATCH', 'https://api.qrhero.com/v1/brands/01HXYZBRANDULID00000000001', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'json' => {
"name": "Automation token",
"slug": "launch-2026",
"brand_kit": {
"primary_color": "#4f46e5"
},
"settings": {
"locale": "en"
},
"primary_domain_ulid": "01HXYZDOMAINULID0000000001"
},
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(
'{"name":"Automation token","slug":"launch-2026","brand_kit":{"primary_color":"#4f46e5"},"settings":{"locale":"en"},"primary_domain_ulid":"01HXYZDOMAINULID0000000001"}',
Encoding.UTF8,
"application/json");
var response = await client.PATCHAsync("https://api.qrhero.com/v1/brands/01HXYZBRANDULID00000000001", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
Domains
/v1/domains
domains.list
List domains
Includes shared fallback hosts and organization custom domains.
- Ability
-
domains.view
Example response
{
"data": [
{
"ulid": "01HXYZDOMAINULID0000000001",
"host": "links.example.com",
"type": "custom",
"status": "active",
"ssl_status": "active",
"is_primary": true,
"is_shared": false,
"verified_at": "2026-02-01T12:05:00+00:00",
"verification": {
"txt_record_name": "_qrhero-verify.links.example.com",
"txt_record_value": "qrhero-verify=abc123",
"cname_target": "qr.qrhero.link"
},
"created_at": "2026-02-01T12:00:00+00:00",
"updated_at": "2026-07-01T08:30:00+00:00"
}
]
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
array<mixed> | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/domains" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/domains', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/domains'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/domains', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/domains");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/domains
domains.create
Add a custom domain
- Ability
-
domains.manage
Request body schema
| Field | Type | Required | Description |
|---|---|---|---|
host |
string | required | required hostname (e.g. links.example.com) |
verify |
boolean | optional | optional boolean — attempt immediate TXT verification |
Example response
{
"data": {
"ulid": "01HXYZDOMAINULID0000000001",
"host": "links.example.com",
"type": "custom",
"status": "active",
"ssl_status": "active",
"is_primary": true,
"is_shared": false,
"verified_at": "2026-02-01T12:05:00+00:00",
"verification": {
"txt_record_name": "_qrhero-verify.links.example.com",
"txt_record_value": "qrhero-verify=abc123",
"cname_target": "qr.qrhero.link"
},
"created_at": "2026-02-01T12:00:00+00:00",
"updated_at": "2026-07-01T08:30:00+00:00"
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
Domain | required | — |
Code samples
curl -sS -X POST "https://api.qrhero.com/v1/domains" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"host": "links.example.com",
"verify": true
}'
const response = await fetch('https://api.qrhero.com/v1/domains', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"host": "links.example.com",
"verify": true
}),
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/domains'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
'Content-Type': 'application/json',
}
payload = {
"host": "links.example.com",
"verify": true
}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.qrhero.com/v1/domains', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'json' => {
"host": "links.example.com",
"verify": true
},
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(
'{"host":"links.example.com","verify":true}',
Encoding.UTF8,
"application/json");
var response = await client.POSTAsync("https://api.qrhero.com/v1/domains", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/domains/{domain_ulid}
domains.update
Verify or update a domain
- Ability
-
domains.manage
Request body schema
| Field | Type | Required | Description |
|---|---|---|---|
verify |
boolean | optional | optional boolean — re-check TXT ownership |
refresh_ssl |
boolean | optional | optional boolean |
is_primary |
boolean | optional | optional boolean |
Example response
{
"data": {
"ulid": "01HXYZDOMAINULID0000000001",
"host": "links.example.com",
"type": "custom",
"status": "active",
"ssl_status": "active",
"is_primary": true,
"is_shared": false,
"verified_at": "2026-02-01T12:05:00+00:00",
"verification": {
"txt_record_name": "_qrhero-verify.links.example.com",
"txt_record_value": "qrhero-verify=abc123",
"cname_target": "qr.qrhero.link"
},
"created_at": "2026-02-01T12:00:00+00:00",
"updated_at": "2026-07-01T08:30:00+00:00"
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
Domain | required | — |
Code samples
curl -sS -X PATCH "https://api.qrhero.com/v1/domains/01HXYZDOMAINULID0000000001" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"verify": true,
"refresh_ssl": true,
"is_primary": true
}'
const response = await fetch('https://api.qrhero.com/v1/domains/01HXYZDOMAINULID0000000001', {
method: 'PATCH',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"verify": true,
"refresh_ssl": true,
"is_primary": true
}),
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/domains/01HXYZDOMAINULID0000000001'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
'Content-Type': 'application/json',
}
payload = {
"verify": true,
"refresh_ssl": true,
"is_primary": true
}
response = requests.patch(url, headers=headers, json=payload)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('PATCH', 'https://api.qrhero.com/v1/domains/01HXYZDOMAINULID0000000001', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'json' => {
"verify": true,
"refresh_ssl": true,
"is_primary": true
},
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(
'{"verify":true,"refresh_ssl":true,"is_primary":true}',
Encoding.UTF8,
"application/json");
var response = await client.PATCHAsync("https://api.qrhero.com/v1/domains/01HXYZDOMAINULID0000000001", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
QR codes
/v1/qr-codes
codes.list
List QR codes
Returns all QR codes in the organization with destination, status, and public URL metadata.
- Ability
-
codes.view
Example response
{
"data": [
{
"ulid": "01HXYZCODEULID000000000001",
"name": "Launch 2026",
"slug": "acme-marketing/launch-2026",
"type": "url",
"status": "active",
"public_url": "https://links.example.com/acme-marketing/launch-2026",
"destination": "https://example.com/launch",
"routing": {
"rules": []
},
"schedule": {
"enabled": false
},
"password": false,
"date_begin": null,
"expire_at": null,
"redirect_cap": null,
"redirects_count": 142,
"utm_params": null,
"device_routing": null,
"language_routing": null,
"tracking_pixels": null,
"custom_js": null,
"landing_config": null,
"prelander_enabled": false,
"prelander_seconds": null,
"prelander_message": null,
"brand": {
"ulid": "01HXYZBRANDULID00000000001",
"name": "Summer Campaign"
},
"domain": {
"ulid": "01HXYZDOMAINULID0000000001",
"host": "links.example.com"
},
"style": {
"ulid": "01HXYZSTYLEULID00000000001",
"name": "Brand default"
},
"created_at": "2026-03-01T09:00:00+00:00",
"updated_at": "2026-07-01T08:30:00+00:00"
}
]
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
array<mixed> | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/qr-codes" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/qr-codes', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/qr-codes'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/qr-codes', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/qr-codes");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/qr-codes/{code_ulid}
codes.read
Read a QR code
Returns a single QR code with routing, schedule, and style references.
- Ability
-
codes.view
Example response
{
"data": {
"ulid": "01HXYZCODEULID000000000001",
"name": "Launch 2026",
"slug": "acme-marketing/launch-2026",
"type": "url",
"status": "active",
"public_url": "https://links.example.com/acme-marketing/launch-2026",
"destination": "https://example.com/launch",
"routing": {
"rules": []
},
"schedule": {
"enabled": false
},
"password": false,
"date_begin": null,
"expire_at": null,
"redirect_cap": null,
"redirects_count": 142,
"utm_params": null,
"device_routing": null,
"language_routing": null,
"tracking_pixels": null,
"custom_js": null,
"landing_config": null,
"prelander_enabled": false,
"prelander_seconds": null,
"prelander_message": null,
"brand": {
"ulid": "01HXYZBRANDULID00000000001",
"name": "Summer Campaign"
},
"domain": {
"ulid": "01HXYZDOMAINULID0000000001",
"host": "links.example.com"
},
"style": {
"ulid": "01HXYZSTYLEULID00000000001",
"name": "Brand default"
},
"created_at": "2026-03-01T09:00:00+00:00",
"updated_at": "2026-07-01T08:30:00+00:00"
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
QrCode | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/qr-codes
codes.create
Create a QR code
Creates a dynamic QR code on the chosen domain. The stored slug is org-slug/individual-slug.
- Ability
-
codes.create
Request body schema
| Field | Type | Required | Description |
|---|---|---|---|
slug |
string | required | required individual slug (stored as org-slug/slug) |
destination |
object | required | required URL or { "url": "..." } object |
domain_ulid |
string | required | required ULID |
name |
string | optional | optional string |
brand_ulid |
string | optional | optional ULID |
style_ulid |
string | optional | optional ULID |
redirect_cap |
integer | optional | optional integer (plan-gated) |
password |
string | optional | optional string (plan-gated) |
routing |
object | optional | optional routing rules object |
schedule |
object | optional | optional schedule object |
Example response
{
"data": {
"ulid": "01HXYZCODEULID000000000001",
"name": "Launch 2026",
"slug": "acme-marketing/launch-2026",
"type": "url",
"status": "active",
"public_url": "https://links.example.com/acme-marketing/launch-2026",
"destination": "https://example.com/launch",
"routing": {
"rules": []
},
"schedule": {
"enabled": false
},
"password": false,
"date_begin": null,
"expire_at": null,
"redirect_cap": null,
"redirects_count": 142,
"utm_params": null,
"device_routing": null,
"language_routing": null,
"tracking_pixels": null,
"custom_js": null,
"landing_config": null,
"prelander_enabled": false,
"prelander_seconds": null,
"prelander_message": null,
"brand": {
"ulid": "01HXYZBRANDULID00000000001",
"name": "Summer Campaign"
},
"domain": {
"ulid": "01HXYZDOMAINULID0000000001",
"host": "links.example.com"
},
"style": {
"ulid": "01HXYZSTYLEULID00000000001",
"name": "Brand default"
},
"created_at": "2026-03-01T09:00:00+00:00",
"updated_at": "2026-07-01T08:30:00+00:00"
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
QrCode | required | — |
Code samples
curl -sS -X POST "https://api.qrhero.com/v1/qr-codes" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"slug": "launch-2026",
"destination": {
"url": "https://example.com"
},
"domain_ulid": "01HXYZDOMAINULID0000000001",
"name": "Automation token",
"brand_ulid": "01HXYZDOMAINULID0000000001",
"style_ulid": "01HXYZDOMAINULID0000000001",
"redirect_cap": 100,
"password": "example",
"routing": {
"rules": []
},
"schedule": {
"enabled": false
}
}'
const response = await fetch('https://api.qrhero.com/v1/qr-codes', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"slug": "launch-2026",
"destination": {
"url": "https://example.com"
},
"domain_ulid": "01HXYZDOMAINULID0000000001",
"name": "Automation token",
"brand_ulid": "01HXYZDOMAINULID0000000001",
"style_ulid": "01HXYZDOMAINULID0000000001",
"redirect_cap": 100,
"password": "example",
"routing": {
"rules": []
},
"schedule": {
"enabled": false
}
}),
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/qr-codes'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
'Content-Type': 'application/json',
}
payload = {
"slug": "launch-2026",
"destination": {
"url": "https://example.com"
},
"domain_ulid": "01HXYZDOMAINULID0000000001",
"name": "Automation token",
"brand_ulid": "01HXYZDOMAINULID0000000001",
"style_ulid": "01HXYZDOMAINULID0000000001",
"redirect_cap": 100,
"password": "example",
"routing": {
"rules": []
},
"schedule": {
"enabled": false
}
}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.qrhero.com/v1/qr-codes', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'json' => {
"slug": "launch-2026",
"destination": {
"url": "https://example.com"
},
"domain_ulid": "01HXYZDOMAINULID0000000001",
"name": "Automation token",
"brand_ulid": "01HXYZDOMAINULID0000000001",
"style_ulid": "01HXYZDOMAINULID0000000001",
"redirect_cap": 100,
"password": "example",
"routing": {
"rules": []
},
"schedule": {
"enabled": false
}
},
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(
'{"slug":"launch-2026","destination":{"url":"https://example.com"},"domain_ulid":"01HXYZDOMAINULID0000000001","name":"Automation token","brand_ulid":"01HXYZDOMAINULID0000000001","style_ulid":"01HXYZDOMAINULID0000000001","redirect_cap":100,"password":"example","routing":{"rules":[]},"schedule":{"enabled":false}}',
Encoding.UTF8,
"application/json");
var response = await client.POSTAsync("https://api.qrhero.com/v1/qr-codes", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/qr-codes/{code_ulid}
codes.update
Update a QR code
Partial update of code fields. Plan-gated add-ons are rejected when the feature is off.
- Ability
-
codes.update
Request body schema
| Field | Type | Required | Description |
|---|---|---|---|
destination |
object | optional | optional URL or object |
status |
string | optional | optional status string |
name |
string | optional | optional string |
redirect_cap |
integer | optional | optional integer |
routing |
object | optional | optional object |
Example response
{
"data": {
"ulid": "01HXYZCODEULID000000000001",
"name": "Launch 2026",
"slug": "acme-marketing/launch-2026",
"type": "url",
"status": "active",
"public_url": "https://links.example.com/acme-marketing/launch-2026",
"destination": "https://example.com/launch",
"routing": {
"rules": []
},
"schedule": {
"enabled": false
},
"password": false,
"date_begin": null,
"expire_at": null,
"redirect_cap": null,
"redirects_count": 142,
"utm_params": null,
"device_routing": null,
"language_routing": null,
"tracking_pixels": null,
"custom_js": null,
"landing_config": null,
"prelander_enabled": false,
"prelander_seconds": null,
"prelander_message": null,
"brand": {
"ulid": "01HXYZBRANDULID00000000001",
"name": "Summer Campaign"
},
"domain": {
"ulid": "01HXYZDOMAINULID0000000001",
"host": "links.example.com"
},
"style": {
"ulid": "01HXYZSTYLEULID00000000001",
"name": "Brand default"
},
"created_at": "2026-03-01T09:00:00+00:00",
"updated_at": "2026-07-01T08:30:00+00:00"
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
QrCode | required | — |
Code samples
curl -sS -X PATCH "https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"destination": {
"url": "https://example.com"
},
"status": "active",
"name": "Automation token",
"redirect_cap": 100,
"routing": {
"rules": []
}
}'
const response = await fetch('https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001', {
method: 'PATCH',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"destination": {
"url": "https://example.com"
},
"status": "active",
"name": "Automation token",
"redirect_cap": 100,
"routing": {
"rules": []
}
}),
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
'Content-Type': 'application/json',
}
payload = {
"destination": {
"url": "https://example.com"
},
"status": "active",
"name": "Automation token",
"redirect_cap": 100,
"routing": {
"rules": []
}
}
response = requests.patch(url, headers=headers, json=payload)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('PATCH', 'https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'json' => {
"destination": {
"url": "https://example.com"
},
"status": "active",
"name": "Automation token",
"redirect_cap": 100,
"routing": {
"rules": []
}
},
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(
'{"destination":{"url":"https://example.com"},"status":"active","name":"Automation token","redirect_cap":100,"routing":{"rules":[]}}',
Encoding.UTF8,
"application/json");
var response = await client.PATCHAsync("https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/qr-codes/{code_ulid}
codes.delete
Delete a QR code
Soft-deletes the code. Returns 204 No Content.
- Ability
-
codes.delete
Code samples
curl -sS -X DELETE "https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001', {
method: 'DELETE',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.delete(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('DELETE', 'https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.DeleteAsync("https://api.qrhero.com/v1/qr-codes/01HXYZCODEULID000000000001");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
Bulk import
/v1/qr-codes/bulk
codes.create
Stage a bulk QR code import
Two-phase flow: stage rows, review preview, then confirm. Returns a confirm_token.
- Ability
-
codes.create
Request body schema
| Field | Type | Required | Description |
|---|---|---|---|
rows |
array<object> | required | required array of row objects |
defaults.domain_ulid |
string | optional | optional default domain ULID |
defaults.brand_ulid |
string | optional | optional default brand ULID |
Example response
{
"data": {
"ulid": "01HXYZIMPORTULID0000000001",
"type": "qr_codes",
"status": "staged",
"source": "api",
"awaiting_confirmation": true,
"total_rows": 2,
"processed_rows": 0,
"success_count": 0,
"failed_count": 0,
"skipped_count": 0,
"valid_row_count": 2,
"progress_percent": 0,
"preview_errors": [],
"error_message": null,
"has_error_report": false,
"confirmed_at": null,
"completed_at": null,
"created_at": "2026-07-01T10:00:00+00:00",
"updated_at": "2026-07-01T10:00:00+00:00"
},
"meta": {
"confirm_token": "CONFIRM_TOKEN_FROM_STAGE"
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
BulkImport | required | — |
meta.confirm_token |
string | required | — |
Code samples
curl -sS -X POST "https://api.qrhero.com/v1/qr-codes/bulk" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"rows": [
{
"slug": "row-1",
"destination": "https://example.com/1"
}
],
"defaults": {
"domain_ulid": "01HXYZDOMAINULID0000000001",
"brand_ulid": "01HXYZDOMAINULID0000000001"
}
}'
const response = await fetch('https://api.qrhero.com/v1/qr-codes/bulk', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"rows": [
{
"slug": "row-1",
"destination": "https://example.com/1"
}
],
"defaults": {
"domain_ulid": "01HXYZDOMAINULID0000000001",
"brand_ulid": "01HXYZDOMAINULID0000000001"
}
}),
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/qr-codes/bulk'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
'Content-Type': 'application/json',
}
payload = {
"rows": [
{
"slug": "row-1",
"destination": "https://example.com/1"
}
],
"defaults": {
"domain_ulid": "01HXYZDOMAINULID0000000001",
"brand_ulid": "01HXYZDOMAINULID0000000001"
}
}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.qrhero.com/v1/qr-codes/bulk', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'json' => {
"rows": [
{
"slug": "row-1",
"destination": "https://example.com/1"
}
],
"defaults": {
"domain_ulid": "01HXYZDOMAINULID0000000001",
"brand_ulid": "01HXYZDOMAINULID0000000001"
}
},
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(
'{"rows":[{"slug":"row-1","destination":"https://example.com/1"}],"defaults":{"domain_ulid":"01HXYZDOMAINULID0000000001","brand_ulid":"01HXYZDOMAINULID0000000001"}}',
Encoding.UTF8,
"application/json");
var response = await client.POSTAsync("https://api.qrhero.com/v1/qr-codes/bulk", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/qr-codes/bulk/{import_ulid}
codes.read
Read bulk import status
Returns staging preview, validation errors, and execution status for a bulk import job.
- Ability
-
codes.view
Example response
{
"data": {
"ulid": "01HXYZIMPORTULID0000000001",
"type": "qr_codes",
"status": "awaiting_confirmation",
"source": "api",
"awaiting_confirmation": true,
"total_rows": 2,
"processed_rows": 0,
"success_count": 0,
"failed_count": 0,
"skipped_count": 0,
"valid_row_count": 2,
"progress_percent": 0,
"preview_errors": [],
"error_message": null,
"has_error_report": false,
"confirmed_at": null,
"completed_at": null,
"created_at": "2026-07-01T10:00:00+00:00",
"updated_at": "2026-07-01T10:00:00+00:00"
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
BulkImport | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/qr-codes/bulk/01HXYZIMPORTULID0000000001" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/qr-codes/bulk/01HXYZIMPORTULID0000000001', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/qr-codes/bulk/01HXYZIMPORTULID0000000001'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/qr-codes/bulk/01HXYZIMPORTULID0000000001', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/qr-codes/bulk/01HXYZIMPORTULID0000000001");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/qr-codes/bulk/{import_ulid}/confirm
codes.create
Confirm and execute bulk import
- Ability
-
codes.create
Request body schema
| Field | Type | Required | Description |
|---|---|---|---|
confirm_token |
string | required | required string from staging response |
Example response
{
"data": {
"ulid": "01HXYZIMPORTULID0000000001",
"type": "qr_codes",
"status": "awaiting_confirmation",
"source": "api",
"awaiting_confirmation": true,
"total_rows": 2,
"processed_rows": 0,
"success_count": 0,
"failed_count": 0,
"skipped_count": 0,
"valid_row_count": 2,
"progress_percent": 0,
"preview_errors": [],
"error_message": null,
"has_error_report": false,
"confirmed_at": null,
"completed_at": null,
"created_at": "2026-07-01T10:00:00+00:00",
"updated_at": "2026-07-01T10:00:00+00:00"
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
BulkImport | required | — |
Code samples
curl -sS -X POST "https://api.qrhero.com/v1/qr-codes/bulk/01HXYZIMPORTULID0000000001/confirm" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"confirm_token": "CONFIRM_TOKEN_FROM_STAGE"
}'
const response = await fetch('https://api.qrhero.com/v1/qr-codes/bulk/01HXYZIMPORTULID0000000001/confirm', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"confirm_token": "CONFIRM_TOKEN_FROM_STAGE"
}),
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/qr-codes/bulk/01HXYZIMPORTULID0000000001/confirm'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
'Content-Type': 'application/json',
}
payload = {
"confirm_token": "CONFIRM_TOKEN_FROM_STAGE"
}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.qrhero.com/v1/qr-codes/bulk/01HXYZIMPORTULID0000000001/confirm', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'json' => {
"confirm_token": "CONFIRM_TOKEN_FROM_STAGE"
},
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(
'{"confirm_token":"CONFIRM_TOKEN_FROM_STAGE"}',
Encoding.UTF8,
"application/json");
var response = await client.POSTAsync("https://api.qrhero.com/v1/qr-codes/bulk/01HXYZIMPORTULID0000000001/confirm", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
QR styles
/v1/qr-styles
styles.list
List QR styles
Returns style presets for the organization, optionally filtered by brand.
- Ability
-
styles.manage
Query parameters
brand_ulid— optional filter
Example response
{
"data": [
{
"ulid": "01HXYZSTYLEULID00000000001",
"name": "Brand default",
"config": {
"type": "square",
"margin": 2
},
"is_preset": true,
"brand": {
"ulid": "01HXYZBRANDULID00000000001",
"name": "Summer Campaign"
},
"created_at": "2026-03-01T09:00:00+00:00",
"updated_at": "2026-07-01T08:30:00+00:00"
}
]
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
array<mixed> | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/qr-styles?brand_ulid=01HXYZBRANDULID00000000001" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/qr-styles?brand_ulid=01HXYZBRANDULID00000000001', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/qr-styles?brand_ulid=01HXYZBRANDULID00000000001'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/qr-styles?brand_ulid=01HXYZBRANDULID00000000001', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/qr-styles?brand_ulid=01HXYZBRANDULID00000000001");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/qr-styles
styles.create
Create a QR style preset
Creates a reusable qr_styles.config preset for the designer and render pipeline.
- Ability
-
styles.manage
Request body schema
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | required | required string |
config |
object | required | required qr_styles.config object |
brand_ulid |
string | optional | optional ULID |
is_preset |
boolean | optional | optional boolean |
Example response
{
"data": {
"ulid": "01HXYZSTYLEULID00000000001",
"name": "Brand default",
"config": {
"type": "square",
"margin": 2
},
"is_preset": true,
"brand": {
"ulid": "01HXYZBRANDULID00000000001",
"name": "Summer Campaign"
},
"created_at": "2026-03-01T09:00:00+00:00",
"updated_at": "2026-07-01T08:30:00+00:00"
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
QrStyle | required | — |
Code samples
curl -sS -X POST "https://api.qrhero.com/v1/qr-styles" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"name": "Automation token",
"config": {
"type": "square",
"margin": 2
},
"brand_ulid": "01HXYZDOMAINULID0000000001",
"is_preset": true
}'
const response = await fetch('https://api.qrhero.com/v1/qr-styles', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Automation token",
"config": {
"type": "square",
"margin": 2
},
"brand_ulid": "01HXYZDOMAINULID0000000001",
"is_preset": true
}),
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/qr-styles'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
'Content-Type': 'application/json',
}
payload = {
"name": "Automation token",
"config": {
"type": "square",
"margin": 2
},
"brand_ulid": "01HXYZDOMAINULID0000000001",
"is_preset": true
}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.qrhero.com/v1/qr-styles', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'json' => {
"name": "Automation token",
"config": {
"type": "square",
"margin": 2
},
"brand_ulid": "01HXYZDOMAINULID0000000001",
"is_preset": true
},
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(
'{"name":"Automation token","config":{"type":"square","margin":2},"brand_ulid":"01HXYZDOMAINULID0000000001","is_preset":true}',
Encoding.UTF8,
"application/json");
var response = await client.POSTAsync("https://api.qrhero.com/v1/qr-styles", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
Wallet
/v1/wallet
wallet.read
Read prepaid wallet balance and ledger
Returns the organization wallet balance and paginated wallet_transactions history. Wallet top-ups and other billing writes are UI-only.
- Ability
-
wallet.view
Query parameters
page— optional page number (default 1)per_page— optional page size 1–100 (default 25)
Example response
{
"data": {
"balance": "125.50",
"currency": "EUR",
"low_balance_threshold": "10.00",
"updated_at": "2026-07-01T08:30:00+00:00",
"transactions": {
"data": [
{
"ulid": "01HXYZWTXULID000000000001",
"type": "debit",
"amount": "-0.01",
"balance_after": "125.50",
"reference_type": "api_usage",
"created_at": "2026-07-01T08:00:00+00:00"
}
],
"meta": {
"current_page": 1,
"last_page": 1,
"per_page": 25,
"total": 1
}
}
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
unknown | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/wallet?page=1&per_page=25" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/wallet?page=1&per_page=25', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/wallet?page=1&per_page=25'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/wallet?page=1&per_page=25', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/wallet?page=1&per_page=25");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
Tokens
/v1/tokens/abilities
List assignable token abilities
Returns abilities the current user may grant for this organization, plus the full catalog.
- Ability
-
api.tokens.manage
Example response
{
"assignable": [
"codes.view",
"codes.create",
"analytics.view"
],
"all": [
"codes.view",
"codes.create",
"analytics.view",
"mcp.access"
]
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
assignable |
array<string> | required | — |
all |
array<string> | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/tokens/abilities" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/tokens/abilities', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/tokens/abilities'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/tokens/abilities', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/tokens/abilities");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/tokens
List API tokens
Lists personal access tokens for the authenticated user in the current organization.
- Ability
-
api.tokens.manage
Example response
{
"data": [
{
"id": 42,
"name": "CI automation",
"abilities": [
"codes.view",
"codes.create",
"mcp.access"
],
"last_used_at": "2026-07-01T07:55:00+00:00",
"expires_at": "2027-12-31T23:59:59+00:00",
"created_at": "2026-01-15T10:00:00+00:00"
}
]
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
data |
array<mixed> | required | — |
Code samples
curl -sS "https://api.qrhero.com/v1/tokens" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/tokens', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/tokens'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.qrhero.com/v1/tokens', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://api.qrhero.com/v1/tokens");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/tokens
Create an API token
- Ability
-
api.tokens.manage
Request body schema
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | required | required string |
abilities |
array<object> | optional | optional array (default ["*"]) |
expires_at |
string (date-time) | optional | optional ISO8601 datetime |
Example response
{
"token": "1|plainTextSecretShownOnce",
"data": {
"id": 42,
"name": "CI automation",
"abilities": [
"codes.view",
"codes.create",
"mcp.access"
],
"expires_at": "2027-12-31T23:59:59+00:00"
}
}
Response schema
| Field | Type | Required | Description |
|---|---|---|---|
token |
string | required | Plain-text secret shown once. |
data |
ApiToken | required | — |
Code samples
curl -sS -X POST "https://api.qrhero.com/v1/tokens" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"name": "Automation token",
"abilities": [
"codes.view",
"codes.create"
],
"expires_at": "2027-12-31T23:59:59Z"
}'
const response = await fetch('https://api.qrhero.com/v1/tokens', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Automation token",
"abilities": [
"codes.view",
"codes.create"
],
"expires_at": "2027-12-31T23:59:59Z"
}),
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/tokens'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
'Content-Type': 'application/json',
}
payload = {
"name": "Automation token",
"abilities": [
"codes.view",
"codes.create"
],
"expires_at": "2027-12-31T23:59:59Z"
}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.qrhero.com/v1/tokens', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'json' => {
"name": "Automation token",
"abilities": [
"codes.view",
"codes.create"
],
"expires_at": "2027-12-31T23:59:59Z"
},
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(
'{"name":"Automation token","abilities":["codes.view","codes.create"],"expires_at":"2027-12-31T23:59:59Z"}',
Encoding.UTF8,
"application/json");
var response = await client.POSTAsync("https://api.qrhero.com/v1/tokens", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
/v1/tokens/{token_id}
Revoke an API token
Returns 204 No Content.
- Ability
-
api.tokens.manage
Code samples
curl -sS -X DELETE "https://api.qrhero.com/v1/tokens/42" \
-H "Authorization: Bearer YOUR_QRHERO_TOKEN" \
-H "Accept: application/json"
const response = await fetch('https://api.qrhero.com/v1/tokens/42', {
method: 'DELETE',
headers: {
Authorization: 'Bearer YOUR_QRHERO_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();
console.log(data);
import requests
url = 'https://api.qrhero.com/v1/tokens/42'
headers = {
'Authorization': 'Bearer YOUR_QRHERO_TOKEN',
'Accept': 'application/json',
}
response = requests.delete(url, headers=headers)
response.raise_for_status()
print(response.json())
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('DELETE', 'https://api.qrhero.com/v1/tokens/42', [
'headers' => [
'Authorization' => 'Bearer YOUR_QRHERO_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody()->getContents(), true);
print_r($data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_QRHERO_TOKEN");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.DeleteAsync("https://api.qrhero.com/v1/tokens/42");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);