{"openapi":"3.1.0","info":{"title":"QR Hero Public API","version":"v1","description":"Organization-scoped REST API for QR Hero. Authenticate with Sanctum personal access tokens (Bearer). Requires the api_access plan feature.","contact":{"name":"QR Hero Developer Docs","url":"https:\/\/docs.qrhero.com\/api"}},"servers":[{"url":"https:\/\/api.qrhero.com","description":"API host"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Sanctum personal access token","description":"Organization-scoped token with ability list. Create tokens in the dashboard or via POST \/v1\/tokens."}},"schemas":{"PlanSummary":{"type":"object","properties":{"code":{"type":"string","description":"Plan code identifier."},"name":{"type":"string","description":"Human-readable plan name."}},"required":["code","name"]},"Organization":{"type":"object","properties":{"ulid":{"type":"string","description":"Organization ULID."},"name":{"type":"string"},"slug":{"type":"string"},"locale":{"type":"string"},"currency":{"type":"string","description":"Billing currency code."},"plan":{"oneOf":[{"$ref":"#\/components\/schemas\/PlanSummary"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["ulid","name","slug","locale","currency"]},"Brand":{"type":"object","properties":{"ulid":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"brand_kit":{"type":"object","additionalProperties":true},"settings":{"type":"object","additionalProperties":true},"primary_domain":{"oneOf":[{"type":"object","properties":{"ulid":{"type":"string"},"host":{"type":"string"}}},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["ulid","name","slug"]},"Domain":{"type":"object","properties":{"ulid":{"type":"string"},"host":{"type":"string"},"type":{"type":"string","enum":["custom","fallback"]},"status":{"type":"string"},"ssl_status":{"type":"string"},"is_primary":{"type":"boolean"},"is_shared":{"type":"boolean"},"verified_at":{"type":["string","null"],"format":"date-time"},"verification":{"type":"object","additionalProperties":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["ulid","host","type","status"]},"QrCode":{"type":"object","properties":{"ulid":{"type":"string"},"name":{"type":["string","null"]},"slug":{"type":"string"},"type":{"type":"string"},"status":{"type":"string"},"public_url":{"type":"string","format":"uri"},"destination":{"type":["string","object"]},"routing":{"type":["object","null"]},"schedule":{"type":["object","null"]},"password":{"type":"boolean"},"redirects_count":{"type":"integer"},"brand":{"type":"object"},"domain":{"type":"object"},"style":{"type":["object","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["ulid","slug","type","status","public_url"]},"QrStyle":{"type":"object","properties":{"ulid":{"type":"string"},"name":{"type":"string"},"config":{"type":"object"},"is_preset":{"type":"boolean"},"brand":{"type":["object","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["ulid","name","config"]},"BulkImport":{"type":"object","properties":{"ulid":{"type":"string"},"type":{"type":"string"},"status":{"type":"string"},"source":{"type":["string","null"]},"awaiting_confirmation":{"type":"boolean"},"total_rows":{"type":"integer"},"processed_rows":{"type":"integer"},"success_count":{"type":"integer"},"failed_count":{"type":"integer"},"skipped_count":{"type":"integer"},"valid_row_count":{"type":["integer","null"]},"progress_percent":{"type":"integer"},"preview_errors":{"type":"array"},"error_message":{"type":["string","null"]},"has_error_report":{"type":"boolean"},"confirmed_at":{"type":["string","null"],"format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["ulid","type","status"]},"Wallet":{"type":"object","properties":{"balance":{"type":"string","description":"Decimal balance as string."},"currency":{"type":"string"},"low_balance_threshold":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time"}},"required":["balance","currency"]},"WalletTransaction":{"type":"object","properties":{"ulid":{"type":"string"},"type":{"type":"string"},"amount":{"type":"string"},"balance_after":{"type":"string"},"reference_type":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"}},"required":["ulid","type","amount","balance_after"]},"ApiToken":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"abilities":{"type":"array","items":{"type":"string"}},"last_used_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":["string","null"],"format":"date-time"}},"required":["id","name","abilities"]},"AnalyticsPayload":{"type":"object","properties":{"scope_level":{"type":"string","enum":["organization","brand","code"]},"range_days":{"type":"integer","enum":[7,30,90]},"totals":{"type":"object"},"time_series":{"type":"array","items":{"type":"object"}},"dimension":{"type":"string"},"dimension_label":{"type":"string"},"dimension_breakdown":{"type":"array","items":{"type":"object"}},"child_breakdown":{"type":"array","items":{"type":"object"}},"csv_rows":{"type":"array","items":{"type":"object"}}},"required":["scope_level","range_days","totals"]},"QrCodeAnalyticsPayload":{"type":"object","properties":{"qr_code":{"type":"object"},"range_days":{"type":"integer"},"totals":{"type":"object"},"time_series":{"type":"array","items":{"type":"object"}},"dimension":{"type":"string"},"dimension_label":{"type":"string"},"dimension_breakdown":{"type":"array","items":{"type":"object"}}},"required":["qr_code","range_days","totals"]},"RawExportPayload":{"type":"object","properties":{"qr_code":{"type":"object"},"rows":{"type":"array","items":{"type":"object"}},"meta":{"type":"object","properties":{"count":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"has_more":{"type":"boolean"}}}},"required":["qr_code","rows","meta"]},"StatusResponse":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"version":{"type":"string"},"organization":{"type":"object"},"plan":{"oneOf":[{"$ref":"#\/components\/schemas\/PlanSummary"},{"type":"null"}]},"api":{"type":"object"},"token":{"type":"object"}},"required":["status","version","organization","api","token"]},"TokenCreateResponse":{"type":"object","properties":{"token":{"type":"string","description":"Plain-text secret shown once."},"data":{"$ref":"#\/components\/schemas\/ApiToken"}},"required":["token","data"]},"TokenAbilitiesResponse":{"type":"object","properties":{"assignable":{"type":"array","items":{"type":"string"}},"all":{"type":"array","items":{"type":"string"}}},"required":["assignable","all"]},"BulkImportStageResponse":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/BulkImport"},"meta":{"type":"object","properties":{"confirm_token":{"type":"string"}},"required":["confirm_token"]}},"required":["data","meta"]},"McpToolCallResponse":{"type":"object","properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"type":"integer"},"result":{"type":"object","properties":{"content":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["text"]},"text":{"type":"string","description":"JSON-encoded REST response payload."}}}},"isError":{"type":"boolean"}}}},"required":["jsonrpc","id","result"]},"OrganizationEnvelope":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Organization"}},"required":["data"]},"BrandEnvelope":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Brand"}},"required":["data"]},"BrandListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Brand"}}},"required":["data"]},"DomainEnvelope":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Domain"}},"required":["data"]},"DomainListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Domain"}}},"required":["data"]},"QrCodeEnvelope":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/QrCode"}},"required":["data"]},"QrCodeListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/QrCode"}}},"required":["data"]},"QrStyleEnvelope":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/QrStyle"}},"required":["data"]},"QrStyleListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/QrStyle"}}},"required":["data"]},"BulkImportEnvelope":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/BulkImport"}},"required":["data"]},"ApiTokenListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/ApiToken"}}},"required":["data"]},"AnalyticsEnvelope":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/AnalyticsPayload"}},"required":["data"]},"QrCodeAnalyticsEnvelope":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/QrCodeAnalyticsPayload"}},"required":["data"]},"RawExportEnvelope":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/RawExportPayload"}},"required":["data"]},"WalletEnvelope":{"type":"object","properties":{"data":{"allOf":[{"$ref":"#\/components\/schemas\/Wallet"},{"type":"object","properties":{"transactions":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/WalletTransaction"}},"meta":{"type":"object"}}}}}]}},"required":["data"]}},"responses":{"Unauthorized":{"description":"Missing or invalid token."},"Forbidden":{"description":"Token lacks the required ability or the organization does not have api_access."},"RateLimited":{"description":"Per-minute rate limit exceeded. Retry after the Retry-After header (seconds).","headers":{"Retry-After":{"schema":{"type":"integer"}},"Link":{"schema":{"type":"string"}}}}}},"tags":[{"name":"Status"},{"name":"Organization"},{"name":"Analytics"},{"name":"Brands"},{"name":"Domains"},{"name":"QR codes"},{"name":"Bulk import"},{"name":"QR styles"},{"name":"Wallet"},{"name":"Tokens"}],"paths":{"\/v1\/status":{"get":{"operationId":"status.read","tags":["Status"],"summary":"Health check and token context","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/StatusResponse"},"example":{"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"]}}}}}},"description":"Returns API version, organization context, plan API limits, and the current token metadata."}},"\/v1\/organization":{"get":{"operationId":"organization.read","tags":["Organization"],"summary":"Read organization profile","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/OrganizationEnvelope"},"example":{"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"}}}}}},"description":"Returns safe organization fields (name, locale, currency, plan). Billing identifiers are excluded."}},"\/v1\/analytics":{"get":{"operationId":"analytics.read","tags":["Analytics"],"summary":"Read scan analytics","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/AnalyticsEnvelope"},"example":{"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}]}}}}}},"description":"Hierarchical analytics payload for the organization, a brand, or a single code.\n\nRequired ability: `analytics.view`.","parameters":[{"name":"range","in":"query","description":"7, 30, or 90 (days, default 30)","schema":{"type":"integer","description":"7, 30, or 90 (days, default 30)"}},{"name":"dimension","in":"query","description":"country | device | referrer | language","schema":{"type":"string","description":"country | device | referrer | language"}},{"name":"brand_ulid","in":"query","description":"Optional brand scope","schema":{"type":"string","description":"Optional brand scope"}},{"name":"code_ulid","in":"query","description":"Optional code scope","schema":{"type":"string","description":"Optional code scope"}}]}},"\/v1\/analytics\/export":{"get":{"operationId":"analytics.export","tags":["Analytics"],"summary":"Export analytics payload","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/AnalyticsEnvelope"},"example":{"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}]}}}}}},"description":"Same scope filters as analytics read, plus csv_rows for programmatic export.\n\nRequired ability: `analytics.export`.","parameters":[{"name":"range","in":"query","description":"7, 30, or 90 (days, default 30)","schema":{"type":"integer","description":"7, 30, or 90 (days, default 30)"}},{"name":"dimension","in":"query","description":"country | device | referrer | language","schema":{"type":"string","description":"country | device | referrer | language"}},{"name":"brand_ulid","in":"query","description":"Optional brand scope","schema":{"type":"string","description":"Optional brand scope"}},{"name":"code_ulid","in":"query","description":"Optional code scope","schema":{"type":"string","description":"Optional code scope"}}]}},"\/v1\/analytics\/qr-codes\/{code_ulid}":{"get":{"operationId":"analytics.qr_code.read","tags":["Analytics"],"summary":"Read QR code rollup analytics","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/QrCodeAnalyticsEnvelope"},"example":{"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}]}}}}}},"description":"Per-code scan analytics from the qr_code_scan_daily rollup table.\n\nRequired ability: `analytics.view`.","parameters":[{"name":"code_ulid","in":"path","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","description":"7, 30, or 90 (days, default 30)","schema":{"type":"integer","description":"7, 30, or 90 (days, default 30)"}},{"name":"dimension","in":"query","description":"country | device | referrer | language | provider","schema":{"type":"string","description":"country | device | referrer | language | provider"}}]}},"\/v1\/analytics\/qr-codes\/{code_ulid}\/raw-export":{"get":{"operationId":"analytics.raw_export","tags":["Analytics"],"summary":"Export raw scan rows for a QR code","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/RawExportEnvelope"},"example":{"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}}}}}}},"description":"Paginated raw qr_code_scans rows. Uses a separate, stricter per-minute rate limit.\n\nRequired ability: `analytics.export`.","parameters":[{"name":"code_ulid","in":"path","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","description":"7, 30, or 90 (days, default 30)","schema":{"type":"integer","description":"7, 30, or 90 (days, default 30)"}},{"name":"limit","in":"query","description":"Page size (default 1000, max 5000)","schema":{"type":"integer","description":"Page size (default 1000, max 5000)"}},{"name":"offset","in":"query","description":"Row offset for pagination (default 0)","schema":{"type":"integer","description":"Row offset for pagination (default 0)"}}]}},"\/v1\/brands":{"get":{"operationId":"brands.list","tags":["Brands"],"summary":"List brands","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/BrandListEnvelope"},"example":{"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"}]}}}}},"description":"Returns all brands in the token organization, including brand kit and settings metadata.\n\nRequired ability: `brands.view`."},"post":{"operationId":"brands.create","tags":["Brands"],"summary":"Create a brand","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"201":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/BrandEnvelope"},"example":{"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"}}}}}},"description":"Required ability: `brands.manage`.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"required string"},"slug":{"type":"string","description":"optional alpha_dash"},"brand_kit":{"type":"object","additionalProperties":true,"description":"optional object"},"settings":{"type":"object","additionalProperties":true,"description":"optional object"},"primary_domain_ulid":{"type":"string","description":"optional ULID"}},"required":["name"]}}}}}},"\/v1\/brands\/{brand_ulid}":{"patch":{"operationId":"brands.update","tags":["Brands"],"summary":"Update a brand","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/BrandEnvelope"},"example":{"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"}}}}}},"description":"Partial update of brand fields. Omitted keys are left unchanged.\n\nRequired ability: `brands.manage`.","parameters":[{"name":"brand_ulid","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"optional string"},"slug":{"type":"string","description":"optional alpha_dash"},"brand_kit":{"type":"object","additionalProperties":true,"description":"optional object"},"settings":{"type":"object","additionalProperties":true,"description":"optional object"},"primary_domain_ulid":{"type":"string","description":"optional ULID"}}}}}}}},"\/v1\/domains":{"get":{"operationId":"domains.list","tags":["Domains"],"summary":"List domains","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/DomainListEnvelope"},"example":{"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"}]}}}}},"description":"Includes shared fallback hosts and organization custom domains.\n\nRequired ability: `domains.view`."},"post":{"operationId":"domains.create","tags":["Domains"],"summary":"Add a custom domain","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"201":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/DomainEnvelope"},"example":{"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"}}}}}},"description":"Required ability: `domains.manage`.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"host":{"type":"string","description":"required hostname (e.g. links.example.com)"},"verify":{"type":"boolean","description":"optional boolean \u2014 attempt immediate TXT verification"}},"required":["host"]}}}}}},"\/v1\/domains\/{domain_ulid}":{"patch":{"operationId":"domains.update","tags":["Domains"],"summary":"Verify or update a domain","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/DomainEnvelope"},"example":{"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"}}}}}},"description":"Required ability: `domains.manage`.","parameters":[{"name":"domain_ulid","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"verify":{"type":"boolean","description":"optional boolean \u2014 re-check TXT ownership"},"refresh_ssl":{"type":"boolean","description":"optional boolean"},"is_primary":{"type":"boolean","description":"optional boolean"}}}}}}}},"\/v1\/qr-codes":{"get":{"operationId":"codes.list","tags":["QR codes"],"summary":"List QR codes","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/QrCodeListEnvelope"},"example":{"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"}]}}}}},"description":"Returns all QR codes in the organization with destination, status, and public URL metadata.\n\nRequired ability: `codes.view`."},"post":{"operationId":"codes.create","tags":["QR codes"],"summary":"Create a QR code","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"201":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/QrCodeEnvelope"},"example":{"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"}}}}}},"description":"Creates a dynamic QR code on the chosen domain. The stored slug is org-slug\/individual-slug.\n\nRequired ability: `codes.create`.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","description":"required individual slug (stored as org-slug\/slug)"},"destination":{"type":"object","additionalProperties":true,"description":"required URL or { \"url\": \"...\" } object"},"domain_ulid":{"type":"string","description":"required ULID"},"name":{"type":"string","description":"optional string"},"brand_ulid":{"type":"string","description":"optional ULID"},"style_ulid":{"type":"string","description":"optional ULID"},"redirect_cap":{"type":"integer","description":"optional integer (plan-gated)"},"password":{"type":"string","description":"optional string (plan-gated)"},"routing":{"type":"object","additionalProperties":true,"description":"optional routing rules object"},"schedule":{"type":"object","additionalProperties":true,"description":"optional schedule object"}},"required":["slug","destination","domain_ulid"]}}}}}},"\/v1\/qr-codes\/{code_ulid}":{"get":{"operationId":"codes.read","tags":["QR codes"],"summary":"Read a QR code","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/QrCodeEnvelope"},"example":{"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"}}}}}},"description":"Returns a single QR code with routing, schedule, and style references.\n\nRequired ability: `codes.view`.","parameters":[{"name":"code_ulid","in":"path","required":true,"schema":{"type":"string"}}]},"patch":{"operationId":"codes.update","tags":["QR codes"],"summary":"Update a QR code","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/QrCodeEnvelope"},"example":{"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"}}}}}},"description":"Partial update of code fields. Plan-gated add-ons are rejected when the feature is off.\n\nRequired ability: `codes.update`.","parameters":[{"name":"code_ulid","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"destination":{"type":"object","additionalProperties":true,"description":"optional URL or object"},"status":{"type":"string","description":"optional status string"},"name":{"type":"string","description":"optional string"},"redirect_cap":{"type":"integer","description":"optional integer"},"routing":{"type":"object","additionalProperties":true,"description":"optional object"}}}}}}},"delete":{"operationId":"codes.delete","tags":["QR codes"],"summary":"Delete a QR code","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"204":{"description":"Deleted"}},"description":"Soft-deletes the code. Returns 204 No Content.\n\nRequired ability: `codes.delete`.","parameters":[{"name":"code_ulid","in":"path","required":true,"schema":{"type":"string"}}]}},"\/v1\/qr-codes\/bulk":{"post":{"operationId":"codes.create","tags":["Bulk import"],"summary":"Stage a bulk QR code import","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"201":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/BulkImportStageResponse"},"example":{"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"}}}}}},"description":"Two-phase flow: stage rows, review preview, then confirm. Returns a confirm_token.\n\nRequired ability: `codes.create`.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"rows":{"type":"array","items":{"type":"object"},"description":"required array of row objects"},"defaults.domain_ulid":{"type":"string","description":"optional default domain ULID"},"defaults.brand_ulid":{"type":"string","description":"optional default brand ULID"}},"required":["rows"]}}}}}},"\/v1\/qr-codes\/bulk\/{import_ulid}":{"get":{"operationId":"codes.read","tags":["Bulk import"],"summary":"Read bulk import status","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/BulkImportEnvelope"},"example":{"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"}}}}}},"description":"Returns staging preview, validation errors, and execution status for a bulk import job.\n\nRequired ability: `codes.view`.","parameters":[{"name":"import_ulid","in":"path","required":true,"schema":{"type":"string"}}]}},"\/v1\/qr-codes\/bulk\/{import_ulid}\/confirm":{"post":{"operationId":"codes.create","tags":["Bulk import"],"summary":"Confirm and execute bulk import","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"202":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/BulkImportEnvelope"},"example":{"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"}}}}}},"description":"Required ability: `codes.create`.","parameters":[{"name":"import_ulid","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"confirm_token":{"type":"string","description":"required string from staging response"}},"required":["confirm_token"]}}}}}},"\/v1\/qr-styles":{"get":{"operationId":"styles.list","tags":["QR styles"],"summary":"List QR styles","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/QrStyleListEnvelope"},"example":{"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"}]}}}}},"description":"Returns style presets for the organization, optionally filtered by brand.\n\nRequired ability: `styles.manage`.","parameters":[{"name":"brand_ulid","in":"query","description":"optional filter","schema":{"type":"string","description":"optional filter"}}]},"post":{"operationId":"styles.create","tags":["QR styles"],"summary":"Create a QR style preset","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"201":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/QrStyleEnvelope"},"example":{"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"}}}}}},"description":"Creates a reusable qr_styles.config preset for the designer and render pipeline.\n\nRequired ability: `styles.manage`.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"required string"},"config":{"type":"object","additionalProperties":true,"description":"required qr_styles.config object"},"brand_ulid":{"type":"string","description":"optional ULID"},"is_preset":{"type":"boolean","description":"optional boolean"}},"required":["name","config"]}}}}}},"\/v1\/wallet":{"get":{"operationId":"wallet.read","tags":["Wallet"],"summary":"Read prepaid wallet balance and ledger","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/WalletEnvelope"},"example":{"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}}}}}}}},"description":"Returns the organization wallet balance and paginated wallet_transactions history. Wallet top-ups and other billing writes are UI-only.\n\nRequired ability: `wallet.view`.","parameters":[{"name":"page","in":"query","description":"optional page number (default 1)","schema":{"type":"integer","description":"optional page number (default 1)"}},{"name":"per_page","in":"query","description":"optional page size 1\u2013100 (default 25)","schema":{"type":"integer","description":"optional page size 1\u2013100 (default 25)"}}]}},"\/v1\/tokens\/abilities":{"get":{"operationId":"get__v1_tokens_abilities","tags":["Tokens"],"summary":"List assignable token abilities","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TokenAbilitiesResponse"},"example":{"assignable":["codes.view","codes.create","analytics.view"],"all":["codes.view","codes.create","analytics.view","mcp.access"]}}}}},"description":"Returns abilities the current user may grant for this organization, plus the full catalog.\n\nRequired ability: `api.tokens.manage`."}},"\/v1\/tokens":{"get":{"operationId":"get__v1_tokens","tags":["Tokens"],"summary":"List API tokens","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"200":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiTokenListEnvelope"},"example":{"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"}]}}}}},"description":"Lists personal access tokens for the authenticated user in the current organization.\n\nRequired ability: `api.tokens.manage`."},"post":{"operationId":"post__v1_tokens","tags":["Tokens"],"summary":"Create an API token","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"201":{"description":"Success","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TokenCreateResponse"},"example":{"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"}}}}}},"description":"Required ability: `api.tokens.manage`.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"required string"},"abilities":{"type":"array","items":{"type":"object"},"description":"optional array (default [\"*\"])"},"expires_at":{"type":"string","format":"date-time","description":"optional ISO8601 datetime"}},"required":["name"]}}}}}},"\/v1\/tokens\/{token_id}":{"delete":{"operationId":"delete__v1_tokens_token_id","tags":["Tokens"],"summary":"Revoke an API token","security":[{"bearerAuth":[]}],"responses":{"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"429":{"$ref":"#\/components\/responses\/RateLimited"},"204":{"description":"Deleted"}},"description":"Returns 204 No Content.\n\nRequired ability: `api.tokens.manage`.","parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"integer"}}]}}}}