Autenticación
Autenticación y modelo de seguridad
Toda ruta (salvo las públicas de abajo) requiere Authorization: Bearer <token>.
Tipos de credencial
API key por owner (sk_live_…)
La credencial normal. Cada key pertenece a UN owner y solo puede ver/operar los datos de ese owner (profiles, cuentas, posts…) — recurso ajeno → 403. Puede tener scope (full o profiles con lista de IDs) y permission (read-write o read = solo GET). Es la que usa un agente en nombre de un usuario.
API key admin (interna)
Una sola key global, del backend. Acceso total, bypass del aislamiento por owner. Nunca se entrega a un agente de usuario — es solo para operación interna del servicio.
Sesión de usuario (JWT)
El token de sesión del propio Dashboard web. Es la única credencial que puede crear o revocar API keys — una sk_ nunca puede gestionar otras API keys (evita escalada de privilegios).
Rutas públicas (sin token)
GET /health, GET /llms.txt, GET /webhooks/* (entrantes de plataformas, validan su propia firma), las páginas del sitio, y los GET /connect/*/callback (OAuth).
Gestión de API keys
Solo con sesión de usuario real (no funciona con una sk_). En la práctica, se gestionan desde el Dashboard.
POST/api-keys{ name, expiresIn?(días), scope?('full'|'profiles'), profileIds?, permission?('read-write'|'read'), redirectUris?[] } → { apiKey, key }. La key se muestra una sola vez.
GET/api-keysLista tus keys (sin exponer la key en claro).
PATCH/api-keys/:id{ redirectUris } — edita las URLs de callback permitidas sin recrear la key ni rotar el secreto. Ver
Conectar tu agente.
DELETE/api-keys/:idRevoca la key inmediatamente.
Aislamiento por owner
Cada request se acota al owner del token: un recurso de otro owner responde 403 (existe pero no es tuyo) o 404 (no existe). Una key con scope:'profiles' no puede tocar profiles fuera de su lista, aunque sean del mismo owner.
Errores
Formato uniforme: { "error": "mensaje" }, más un campo "code" estable cuando el error es de plan o de conexión (one_per_network, plan_account_limit, plan_profile_limit, ai_credit_limit, profile_paused) — ramifica por code, no por el texto del mensaje.
400 validación
401 sin auth / key inválida
403 no autorizado (recurso ajeno, o key read-only en POST/PATCH/DELETE)
404 no existe
409 conflicto (p.ej. número ya conectado)
402 límite de plan (con code)
422 la plataforma rechazó la operación (p.ej. la ventana de 24 h de Meta ya cerró)
429 rate-limit
bash
curl https://zoosial.com/profiles \
-H "Authorization: Bearer $SC_API_KEY"