Organizaciones y Workspaces
Descripción general
qr3.app utiliza una jerarquía de dos niveles:
Organization (Firma/Agentur) └── Workspace 1 (Kunde A) └── Workspace 2 (Kunde B) └── Workspace 3 (Internes Team)- Organización — nivel superior, asociada a una cuenta y plan de Stripe
- Workspace — área aislada para códigos QR, escaneos y API-keys
API de Organizaciones
GET /v1/organizations
Devuelve la organización a la que pertenece la API-key actual.
curl https://qr3.app/v1/organizations \ -H "Authorization: Bearer qr3_sk_..."GET /v1/organizations/usage
Devuelve el uso en tiempo real de la organización frente a los límites del plan (sumado de todos los Workspaces y calculado en vivo): scans para el mes de facturación actual (frente a max_scans_per_month) y dynamic_codes, la cantidad de códigos dinámicos activos (frente a max_dynamic_codes). Ninguno de los dos se bloquea al alcanzar el límite; utiliza este endpoint para mostrar el uso y avisos de actualización (upgrade).
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
Crea una nueva organización.
curl -X POST https://qr3.app/v1/organizations \ -H "Authorization: Bearer qr3_sk_..." \ -H "Content-Type: application/json" \ -d '{ "name": "Digital Heroes GmbH", "slug": "digital-heroes", "billing_email": "[email protected]" }'Campos:
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
name | string | ✅ | Nombre para mostrar (máx. 255 caracteres) |
slug | string | ✅ | Amigable para URL, único (mín. 2, máx. 63 caracteres, solo a-z0-9-) |
billing_email | string | — | Correo electrónico de facturación |
PATCH /v1/organizations/:id
Modifica el nombre, el correo de facturación y el correo de notificaciones de la organización.
Solo un org_admin puede modificarlos, en una sesión de Dashboard. Las solicitudes con una API-key se rechazan con 403 (también las claves qr3_sk_ y qr3_test_sk_), por lo que una clave filtrada no puede desviar la dirección de facturación ni la de notificaciones.
DELETE /v1/organizations/:id
Eliminación lógica (soft-delete) de la organización. Todos los Workspaces y códigos QR asociados se conservan, pero ya no son accesibles.
Requiere el rol org_admin (sesión de Dashboard). Las solicitudes con una API-key pura se rechazan con 403; las API-keys nunca alcanzan un rol de administrador, por lo que una clave filtrada no puede eliminar la organización.
API de Workspaces
GET /v1/workspaces
Listar los Workspaces visibles para quien llama: org_admin y el propietario de la organización ven todos los Workspaces de la organización, los demás miembros solo los Workspaces a los que pertenecen y una API-key solo su propio Workspace. Un Workspace que quien llama no puede ver responde con 404 en todas las rutas /v1/workspaces/:id, igual que un ID desconocido.
curl https://qr3.app/v1/workspaces \ -H "Authorization: Bearer qr3_sk_..."POST /v1/workspaces
Crear un nuevo Workspace.
curl -X POST https://qr3.app/v1/workspaces \ -H "Authorization: Bearer qr3_sk_..." \ -H "Content-Type: application/json" \ -d '{ "name": "Kunde Bäckerei Schmidt", "slug": "baeckerei-schmidt", "default_locale": "de", "primary_color": "#8B4513", "approval_required": false }'Con una API-key, solo puede crear un Workspace una clave creada por un org_admin o por el propietario de la organización; cualquier otra clave recibe 403, antes incluso de comprobar el slug (la respuesta no revela qué slugs están ocupados). El rol de quien creó la clave se comprueba en cada solicitud: si se le degrada, su clave pierde el derecho. Una API-key está vinculada a su propio Workspace y después no ve el nuevo: su id figura en la respuesta 201; un org_admin lo abre en el Dashboard y puede crear allí una clave para él. En el Dashboard solo un org_admin puede crear Workspaces.
Campos:
| Campo | Tipo | Por defecto | Descripción |
|---|---|---|---|
name | string | — | Nombre para mostrar (obligatorio) |
slug | string | — | Amigable para URL, único por organización (obligatorio) |
default_locale | string | de | Idioma predeterminado |
approval_required | boolean | false | Reservado para el flujo de aprobación planificado (no implementado) |
primary_color | string | — | Color de marca (#RRGGBB) |
Límites del plan:
| Plan | Máx. Workspaces |
|---|---|
| Free | 1 |
| Pro | 1 |
| Business | 10 |
| Agency | 50 |
| Enterprise | 500 |
PATCH /v1/workspaces/:id
curl -X PATCH https://qr3.app/v1/workspaces/ws_xyz789 \ -H "Authorization: Bearer qr3_sk_..." \ -H "Content-Type: application/json" \ -d '{ "name": "Neuer Name", "approval_required": true }'DELETE /v1/workspaces/:id
Archiva el Workspace. No se puede aplicar al propio Workspace.
Requiere org_admin o ws_admin del Workspace que se va a archivar; los demás roles reciben 403. Un Workspace que quien llama no puede ver responde con 404: para una API-key, es cualquier Workspace excepto el suyo, que tampoco puede archivar.
Audit-Logs
GET /v1/audit-logs
Registro rastreable de todos los cambios en el Workspace.
curl "https://qr3.app/v1/audit-logs?resource_type=codes&limit=50" \ -H "Authorization: Bearer qr3_sk_..."Parámetros de consulta:
| Parámetro | Tipo | Descripción |
|---|---|---|
resource_type | string | Filtrar por recurso: codes, api_keys, webhooks, workspaces |
resource_id | string | Filtrar por ID de recurso específico |
action | string | Filtrar por acción (p. ej., codes.created) |
cursor | string | Cursor de paginación |
limit | integer | Máx. 100 (por defecto: 50) |
Ejemplo de respuesta:
{ "data": [ { "id": "aud_a1b2c3", "actor_type": "api", "action": "codes.created", "resource_type": "codes", "resource_id": "qr_xyz123", "changes": {}, "created_at": "2026-03-15T10:00:00.000Z" } ]}