Autenticación y permisos
Cómo funciona la llave, qué puede hacer, cómo se rota y qué hacer si se filtra.
Toda petición a /v1 va con la llave en la cabecera:
Authorization: Bearer vk_live_a1b2c3...Sin ella, o con una inválida, la respuesta es 401. No decimos cuál de las razones fue
—inválida, revocada, vencida o desde una IP no permitida— porque decirlo le regala
información a quien esté probando llaves a ciegas.
Formato del token
| Parte | Ejemplo | Qué es |
|---|---|---|
| Prefijo | vk_live_ | Una llave real. vk_test_ es una llave de modo de prueba: simula las verificaciones y no toca el libro |
| Secreto | 43 caracteres | 256 bits de entropía |
En nuestra base solo guardamos el SHA-256 del token. Nunca el secreto, nunca en logs.
Los tres candados
Lo que una llave puede hacer es la intersección de tres cosas:
permiso efectivo = permisos de la llave ∩ tu plan ∩ los negocios de la llave-
Permisos de la llave (scopes). Los marcas al crearla. Sin el permiso,
403 SCOPE_REQUIRED— y el error dice cuál falta, no un genérico:{ "error": { "code": "SCOPE_REQUIRED", "details": { "scope": "expenses.read" } } } -
Tu plan. Marcar
expenses.readno sirve si tu plan no incluye el módulo de egresos. En el panel esos permisos salen en gris con candado, y por API la respuesta es403 PLAN_FEATURE_REQUIREDcondetails.feature(expenses_module). Qué incluye tu plan lo diceGET /v1/planenfeatures. Y si cambias a un plan sin esa función, tus llaves no se revocan: se acotan. Si la función vuelve, tu integración revive sola. -
Los negocios de la llave. Una llave nunca ve un negocio que no esté en su lista, aunque se sepa el id. Pedir uno ajeno responde exactamente lo mismo que pedir uno inexistente.
Catálogo de permisos
| Recurso | Permisos |
|---|---|
| Ingresos | incomes.read · incomes.write · incomes.delete |
| Verificación | verifications.write · verifications.read (consultar verificaciones; write también deja consultarlas) |
| Egresos | expenses.read · expenses.write · expenses.delete · expenses.scan (leer facturas con IA) |
| Conciliación bancaria | reconciliation.read · reconciliation.write · reconciliation.delete — guía |
| Categorías | categories.read · categories.write |
| Cuentas por cobrar | receivables.read · receivables.write · receivables.write_off · receivables.void — por qué son cuatro |
| Pagos sospechosos | suspicious.read · suspicious.resolve |
| Negocio | companies.read · branches.read · branches.write · payment_accounts.read · connections.read |
| Equipo | team.read · team.write |
| Reportes | metrics.read · plan.read |
| Webhooks | webhooks.read · webhooks.write |
Pide lo mínimo
Una llave de solo lectura que se filtre es un susto; una con incomes.delete es un
incidente. Si tu integración solo consulta, no marques nada de escritura. Si después necesitas
más, edita la llave (menú de la llave → Editar): los permisos cambian y el secreto sigue
siendo el mismo.
Dónde se administran
Todo esto vive en el panel del negocio:
Integraciones → API pública
(crear una llave va directo al
formulario).
Hace falta el permiso «Gestionar integraciones» (integration.manage), que por defecto
tienen el Dueño y el Administrador.
Desde ahí se crean, se editan (nombre, permisos, IPs permitidas y vencimiento), se rotan y se revocan; y la tabla muestra el prefijo, el alias, el modo (real o Prueba), el resumen de permisos y cuándo y desde qué IP se usó por última vez — que es lo que permite darse cuenta de una llave que nadie usa hace tres meses, o de una que se está usando desde un sitio raro.
La pestaña Historial
muestra cada petición que hicieron las llaves del negocio: ruta, respuesta, tiempo, llave y modo,
con el requestId para soporte. Se guarda 90 días, sin los secretos ni las imágenes.
No se pueden crear llaves desde la API
/v1 no expone ningún endpoint para acuñar, rotar o revocar llaves, y es a propósito: una
llave que pudiera emitir llaves convertiría la fuga de una de solo lectura en una fuga total
—bastaría usarla para emitir otra con todos los permisos—. Eso exige una sesión de una persona
con permiso, y queda con su nombre encima.
Rotar una llave
Rotar genera un secreto nuevo sin dejarte abajo: en el menú de la llave, Rotar (la vieja sirve 24 h) deja la llave vieja funcionando 24 horas, el tiempo de desplegar.
llave vieja ──────────── 24 h ────────────┤ deja de funcionar
llave nueva ├──────────────────────────────────────────────────▶Rota cuando: se te fue alguien del equipo que la tenía, la llave lleva más de un año viva, o por higiene periódica.
Si se te filtró
Rotar ya (se filtró), en el mismo menú: la vieja muere en el acto. Es preferible que tu integración se caiga diez minutos a que alguien más escriba en el libro del negocio.
Después revisa la columna último uso de la llave en el panel: te dice desde qué IP se usó por última vez.
Endurecerla más
Desde Editar, en el menú de la llave:
- Lista de IPs permitidas. Si tu integración corre en un servidor fijo, deja solo esa IP o
su rango (
190.85.0.0/16). Una llave robada deja de servir fuera de ahí (401). - Fecha de vencimiento. Para una integración temporal —una migración, una consultoría— ponle fecha desde el principio en lugar de confiar en que alguien se acuerde de borrarla.
Y como hábito:
- Una llave por sistema. No compartas la misma entre tu ERP y tu bot: cuando toque revocar una, no quieres tumbar los dos.
- Nunca en el navegador. La llave es de servidor. Si va en el frontend, cualquiera la lee en la pestaña de red.