La API pública se autentica con una clave secreta de cuenta en el header
Authorization, con el esquema Bearer:
curl -sS "$KYCAR_API/v1/verification-sessions" \
-H "Authorization: Bearer sk_live_..."
No hay OAuth, ni firma de request, ni claves públicas: una clave, un header.
Formato de las claves
| Campo | Tipo | Descripción |
|---|---|---|
sk_test_… | secreto | Modo prueba. Las sesiones que crea no consumen tokens y nunca fallan por saldo. |
sk_live_… | secreto | Modo producción. Cada sesión descuenta tokens del saldo de la cuenta al crearse. |
El modo NO es un parámetro del request: lo determina la clave. La misma
llamada con sk_test_ y con sk_live_ produce sesiones distintas, en modos
distintos, sobre configuraciones distintas del proyecto.
Cada clave tiene además un id público (key_…) que sí es visible en el
dashboard y sirve para identificarla y revocarla.
Cómo se guardan
Del secreto sólo se persiste su SHA-256. No existe forma de recuperarlo:
- se muestra una única vez, al crearlo;
- el listado del dashboard muestra el id y los metadatos, nunca el secreto;
- los logs de la plataforma tienen redacción activa de
sk_live_/sk_test_, así que una clave filtrada a un log queda tachada en origen.
Permisos
Cada clave se emite con un conjunto de permisos (o scopes) que define qué puede hacer. Son estos cinco, y no hay otros:
| Campo | Tipo | Descripción |
|---|---|---|
sessions:read | lectura | Listar y consultar sesiones de verificación. |
sessions:write | escritura | Crear y cancelar sesiones. Crear una sesión consume tokens. |
webhooks:read | lectura | Listar endpoints de webhook y su historial de entregas. |
webhooks:write | escritura | Alta, baja y modificación de endpoints, pruebas, re-entregas y rotación del secreto de firma. |
usage:read | lectura | Consultar el consumo mensual y exportar el CSV de sesiones. |
Cada endpoint de la referencia declara el permiso que pide, arriba a la derecha de su método y su ruta.
Escribir implica leer sobre el mismo recurso. Una clave con
sessions:write también puede listar y consultar sesiones; no necesita
sessions:read además. Lo que no se cruza son los recursos:
sessions:write no habilita absolutamente nada sobre webhooks ni sobre uso.
Elegir los permisos al crear la clave
En el dashboard, el alta de la clave tiene una casilla por permiso: vienen todas
tildadas y destildás lo que esa integración no necesite. Por API es el campo
scopes del alta:
{ "mode": "live", "name": "backend-prod", "scopes": ["sessions:write"] }
Si no mandás scopes, la clave se emite con todos los permisos: es el
comportamiento histórico de las claves de cuenta. Restringir es explícito y es
lo recomendado — una clave que sólo crea verificaciones no tiene por qué poder
rotar el secreto de tus webhooks.
Cuando falta un permiso
La API responde 403 con problem+json y código insufficient_scope. No es un
401: la clave es válida, lo que falta es el permiso. El cuerpo trae
required_scope con el permiso exacto que hacía falta.
{
"type": "https://docs.kyc.ar/errores#insufficient_scope",
"title": "insufficient_scope",
"status": 403,
"code": "insufficient_scope",
"detail": "la API key no tiene el scope necesario para esta operación: webhooks:write",
"required_scope": "webhooks:write"
}
Reintentar no cambia nada: usá una clave que tenga ese permiso.
Revocar una clave
Se revoca desde el dashboard. La revocación no borra la clave: queda visible y auditable en el listado, pero deja de autorizar.
Rotación sin downtime
- Generá la clave nueva en el dashboard.
- Desplegala en tu backend junto a la vieja (o reemplazala si podés desplegar en caliente).
- Verificá tráfico con la nueva.
- Revocá la vieja.
Las claves son independientes: no hay límite práctico para tener dos activas durante una ventana de rotación.
Errores de autenticación
| Campo | Tipo | Descripción |
|---|---|---|
Falta el header | 403 | El gateway responde {"message":"Forbidden"} sin cuerpo problem+json. No es un error de tu payload: la request nunca llegó al handler. |
Clave desconocida o revocada | 403 | Mismo cuerpo, indistinguible del caso anterior. Es deliberado: no queremos que la API sirva para enumerar claves válidas. |
Cuenta no activa | 403 | Cuenta pendiente de aprobación o suspendida. Aplica también a las claves de prueba: hasta que la cuenta esté activa, la API pública no responde. |
Contexto de autorización roto | 401 | problem+json con code: "unauthorized". Es un caso de plataforma, no de tu integración: si lo ves de forma sostenida, escribinos. |
Límites de tasa
El stage de la API pública aplica un throttling de 20 requests por segundo
sostenidos, con ráfagas de hasta 40. Por encima, API Gateway responde 429.
Algunas operaciones tienen además un límite propio por cuenta:
| Campo | Tipo | Descripción |
|---|---|---|
POST /v1/webhook-endpoints/{id}/test | 10 por minuto | Compartido con el redeliver. Excederlo devuelve 429 con code: "rate_limited". Los intentos rechazados también cuentan: martillar el endpoint no acerca el desbloqueo. |
POST /v1/webhook-deliveries/{id}/redeliver | 10 por minuto | Mismo cupo que la prueba de endpoint. |