Skip to content

Organizations & Workspaces

Overview

qr3.app uses a two-level hierarchy:

Organization (company/agency)
└── Workspace 1 (Client A)
└── Workspace 2 (Client B)
└── Workspace 3 (Internal team)
  • Organization — top level, tied to a Stripe account and plan
  • Workspace — isolated scope for QR codes, scans, and API keys

Organizations API

GET /v1/organizations

Returns the organization the current API key belongs to.

Terminal window
curl https://qr3.app/v1/organizations \
-H "Authorization: Bearer qr3_sk_..."

billing_email, notification_email and stripe_customer_id are returned only to an org_admin and the organization owner, and to an API key created by an org_admin or the owner (checked on every request). Every other role and key gets the three fields as null. The same applies to GET /v1/organizations/:id.

GET /v1/organizations/usage

Returns the organization’s live usage against its plan limits — summed across all workspaces and computed live: scans for the current billing month (vs max_scans_per_month) and dynamic_codes, the count of active dynamic codes (vs max_dynamic_codes). Neither is blocked at the limit, so use this to power usage meters and upgrade prompts.

Terminal window
curl https://qr3.app/v1/organizations/usage \
-H "Authorization: Bearer qr3_sk_..."
{
"data": {
"scans": {
"used": 4120,
"limit": 5000,
"usage_pct": 82,
"remaining": 880,
"period": "2026-06",
"period_start": "2026-06-01T00:00:00.000Z"
},
"dynamic_codes": {
"used": 142,
"limit": 500,
"usage_pct": 28,
"remaining": 358
}
}
}

POST /v1/organizations

Creates a new organization. Only a person signed in to the dashboard can do this: they become the organization’s owner and get its first workspace with the org_admin role. Requests authenticated with an API key are rejected with 403, for every key type and before the body is checked — an API key is bound to its own workspace and would not reach the new organization. An invalid body gives 422 (errors/validation), a slug that is taken 409.

{
"name": "Digital Heroes Ltd",
"slug": "digital-heroes"
}

PATCH /v1/organizations/:id

Updates the organization’s name, billing email and notification email.

Only an org_admin can change them, in a dashboard session. Requests authenticated with an API key are rejected with 403 — qr3_sk_ and qr3_test_sk_ keys included — so a leaked key cannot redirect the billing or notification address.

DELETE /v1/organizations/:id

Soft-deletes the organization and all associated workspaces.

Requires the org_admin role (dashboard session). Requests authenticated with a plain API key are rejected with 403 — API keys never carry an admin role, so a leaked key cannot delete the organization.


Workspaces API

GET /v1/workspaces

Lists the workspaces visible to the caller: org_admin and the organization owner see every workspace of the organization, other members only the workspaces they belong to, and an API key only its own workspace. A workspace the caller cannot see answers 404 on every /v1/workspaces/:id route, exactly like an unknown ID.

POST /v1/workspaces

Terminal window
curl -X POST https://qr3.app/v1/workspaces \
-H "Authorization: Bearer qr3_sk_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Client A — Campaign Q2",
"slug": "client-a-campaign-q2"
}'

With an API key, only a key created by an org_admin or the organization owner may create a workspace; every other key gets 403, before the slug is checked (so the answer does not reveal which slugs are taken). The creator’s role is checked on every request: a key loses the right when its creator is demoted. An API key is bound to its own workspace and does not see the new one afterwards: its id is in the 201 response; an org_admin opens it in the dashboard and can create a key for it there. In the dashboard, only an org_admin may create workspaces.

PATCH /v1/workspaces/:id

Update name, description, or settings.

DELETE /v1/workspaces/:id

Soft-deletes the workspace. Cannot delete the default workspace.

Requires org_admin, or ws_admin of the workspace being archived; other roles get 403. A workspace the caller cannot see answers 404 — for an API key that is every workspace except its own, which it cannot archive either.

The API keys of an archived workspace stop working: every request made with them gets 401.


Plan Limits

PlanWorkspaces
Free1
Pro1
Business10
Agency50
Enterprise500

Audit logs

GET /v1/audit-logs lists audit events for the authenticated workspace, newest first and cursor-paginated.