API reference
The HTTP API uses Laravel Sanctum. Authenticate with a Bearer token. Workspace routes require membership and scoped token abilities for read and write operations.
Authentication model
- Session cookies apply to browser use; programmatic access uses personal access tokens.
- Tokens are created per user and carry one or more abilities, e.g.
workspace:acme-corp:readandworkspace:acme-corp:write. - Read routes require a matching
:read(or:write). Mutating routes require:write.
Base URL
All paths below are relative to your deployment origin. Versioned endpoints are available under /api/v1 and should be preferred for new integrations. Legacy unversioned endpoints remain for backward compatibility during migration.
Rate limiting
Workspace API routes are throttled per authenticated user and workspace (see API_WORKSPACE_REQUESTS_PER_MINUTE in environment configuration, default 120 per rolling minute). Expect HTTP 429 when exceeded.
Endpoints
| Method | Path | Middleware | Description |
|---|---|---|---|
GET |
/api/user |
auth:sanctum |
Returns the authenticated user for the given Bearer token or session. |
GET |
/api/workspaces/{workspace}/tokens |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Lists workspace-scoped API tokens for workspace members (metadata only, no plaintext tokens). |
POST |
/api/workspaces/{workspace}/tokens |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Creates a named personal access token scoped to the workspace. Supports scope=read_only or scope=read_write (default). Plaintext token returned once. |
DELETE |
/api/workspaces/{workspace}/tokens/{tokenId} |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Revokes a workspace token immediately. |
GET |
/api/workspaces/{workspace}/qr-codes |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Paginated list of tracked links (QR records). Optional query: status=active|archived, per_page=1–100. |
POST |
/api/workspaces/{workspace}/qr-codes |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Creates a tracked destination. Requires a role that can manage QR content. Returns 422 when the active-code quota is exceeded. |
GET |
/api/workspaces/{workspace}/qr-codes/{id} |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Returns one QR code scoped to the workspace (implicit binding). |
PATCH |
/api/workspaces/{workspace}/qr-codes/{id} |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Updates title, destination URL, campaign tag, UTM defaults, or status. Reactivating from archived counts toward the active-code quota. |
DELETE |
/api/workspaces/{workspace}/qr-codes/{id} |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Deletes the QR code (owner role required, same as the web app). |
GET |
/api/workspaces/{workspace}/analytics/summary |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Read-only analytics summary (KPIs, trend, device breakdown). Requires Owner, Admin, or Analyst (same as CSV export). Query params: start_date, end_date, qr_code_id, device, campaign (use all or omit to disable a filter). |
GET |
/api/workspaces/{workspace}/analytics/scans |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Paginated scan rows with the same filters as summary/export. Optional: page, per_page (1–100). |
GET |
/api/workspaces/{workspace}/analytics/filters |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
QR code list and distinct campaign values for building filter UIs (export role required). |
GET |
/api/v1/workspaces/{workspace}/audit-logs |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
List audit log events with optional filters: action, actor, from, to. |
GET |
/api/v1/workspaces/{workspace}/audit-logs/export |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Export filtered audit log CSV (Enterprise entitlement required). |
GET |
/api/workspaces/{workspace}/webhooks |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
List outbound webhook endpoints for the workspace. Requires a role that can manage content (Owner/Admin). |
POST |
/api/workspaces/{workspace}/webhooks |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Create endpoint URL + event list and receive a signing secret once in meta.signing_secret. |
PATCH |
/api/workspaces/{workspace}/webhooks/{id} |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Update endpoint URL/description/events/enabled and optionally rotate signing secret with rotate_secret=true. |
DELETE |
/api/workspaces/{workspace}/webhooks/{id} |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Delete endpoint and delivery logs. |
GET |
/api/workspaces/{workspace}/webhooks/{id}/deliveries |
auth:sanctum, workspace.member, workspace.sanctum, workspace.api |
Paginated delivery attempts including status code, attempt number, and error details. |
Create a token (example)
While signed in, POST JSON with a display name. The response includes the plaintext token—store it securely.
curl -X POST "https://qrhub.iutils.net/api/workspaces/{workspace}/tokens" \
-H "Authorization: Bearer {existing_token_or_session_not_used_here}" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"name":"CI export bot","scope":"read_only"}'
In practice, token creation is typically performed from the browser while authenticated; use the same route with your session or an existing token that already has workspace access.
List tokens (example)
curl -X GET "https://qrhub.iutils.net/api/workspaces/{workspace}/tokens" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Revoke token (example)
curl -X DELETE "https://qrhub.iutils.net/api/workspaces/{workspace}/tokens/{tokenId}" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
List QR codes (example)
curl -X GET "https://qrhub.iutils.net/api/workspaces/{workspace}/qr-codes" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Analytics summary (example)
Members without analytics export permission (see Team & roles) receive HTTP 403 on analytics routes.
curl -X GET "https://qrhub.iutils.net/api/workspaces/{workspace}/analytics/summary?start_date=2026-01-01&end_date=2026-01-31" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Analytics scans (example)
curl -X GET "https://qrhub.iutils.net/api/workspaces/{workspace}/analytics/scans?per_page=50&page=1" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Create webhook endpoint (example)
curl -X POST "https://qrhub.iutils.net/api/workspaces/{workspace}/webhooks" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"url":"https://hooks.example.com/scan","event_types":["scan.logged"],"enabled":true}'
List webhook deliveries (example)
curl -X GET "https://qrhub.iutils.net/api/workspaces/{workspace}/webhooks/{id}/deliveries?page=1" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Errors
Versioned routes return a standard error envelope: { error: { code, message, details? } }. Common codes include unauthenticated (401), forbidden (403), not_found (404), validation_failed (422), and rate-limit responses (429).
Idempotency and side effects
GET requests are read-only. POST to create a token is not idempotent—each call mints a new token. Revoke tokens via the DELETE endpoint or the workspace token settings screen.
Audit trail
Creating API tokens may be recorded in the audit log when enabled, including token name and workspace context.
Related guides
Team & roles · Security & privacy · Trust center · Troubleshooting