Empezar
Autenticación y API keys
Cómo crear una llave, qué scopes existen y cómo se comporta ante producción y sandbox.
Toda la API se autentica con un header. No hay OAuth, ni tokens que renovar, ni firmas que calcular.
X-API-Key: fk_a1b2c3d4e5f6...
La credencial
| Propiedad | Valor |
|---|---|
| Formato | fk_ seguido de 64 caracteres hexadecimales |
| Header | X-API-Key |
| Almacenamiento | Solo el hash SHA-256. El texto plano se muestra una vez al crearla y no es recuperable — únicamente revocable. |
| Alcance | Una llave pertenece a una organización. |
| Autorización | El arreglo scopes[] que elegiste al crearla. |
| Dónde se crea | Facty → Configuración → API Keys |
La organización sale de la llave, no de la URL
Las rutas llevan el slug de la organización
(/api/authenticated/{orgSlug}/invoices), pero ese segmento no decide a qué
organización accedes: eso lo decide la llave. Si el slug de la URL no es el de la
llave, la respuesta es 403 ORG_MISMATCH. Un segmento de ruta nunca puede
ampliar el alcance de una credencial.
Producción y preview son bases distintas
Una llave emitida en producción no sirve en un ambiente de preview ni al revés. Si tu producto ofrece los dos modos, guarda una llave por ambiente, por separado.
Scopes
Un scope es un permiso con la forma recurso.verbo. La llave queda acotada
exactamente a los que le marcaste: si a un endpoint le falta el suyo, responde
403 MISSING_SCOPE con el campo required diciendo cuál falta.
| Scope | Permite |
|---|---|
invoices.create | Timbrar CFDI de ingreso, egreso, traslado, nómina y retenciones. Alta de empleados. |
invoices.read | Listar y consultar facturas, saldos, estatus SAT, XML/PDF, empleados. |
invoices.update | Editar borradores. |
invoices.cancel | Cancelar un CFDI o un complemento de pago ante el SAT. |
invoices.send | Enviar el CFDI por correo desde Facty. |
clients.create / clients.read / clients.update / clients.delete | Catálogo de clientes (receptores). |
products.create / products.read / products.update / products.delete | Catálogo de productos y servicios. |
payments.create | Registrar pagos y timbrar complementos de pago (REP). |
payments.read | Consultar pagos registrados. |
accounts.read / accounts.write | Cuentas bancarias y de efectivo. |
transfers.create | Traspasos entre cuentas. |
reports.read | Reportes y resúmenes. |
billing.read | Consultar el saldo de timbres y su historial. |
billing.purchase | Comprar paquetes de timbres. |
audit.read | Bitácora de auditoría. |
org.settings | Configuración de la organización, incluida la gestión de API keys. |
Combinaciones típicas
| Caso de uso | Scopes |
|---|---|
| Timbrar desde un ERP | invoices.create, invoices.read, clients.create, clients.read, products.read |
| Timbrar + complementos de pago | lo anterior + payments.create, payments.read, accounts.read |
| Solo lectura / conciliación | invoices.read, clients.read, payments.read, reports.read |
| Nómina | invoices.create, invoices.read |
| Panel con saldo de timbres | + billing.read |
Un detalle que conviene decir en voz alta
Los scopes sustituyen la búsqueda de rol; no se intersectan con él. Una llave queda confinada a sus propios scopes, pero no se vuelve a acotar contra el rol que hoy tenga la persona que la creó: si a esa persona la degradan, la llave conserva sus scopes hasta que alguien la revoque. Revoca las llaves de quien sale del equipo.
Qué no puede hacer una API key
- No entra a rutas de superadministración.
- No entra a
/api/authenticated/me— una llave autentica a una organización, no a una persona. - No puede crear otras llaves salvo que le des
org.settings, cosa que normalmente no querrás.
Límites de tasa
Los límites son por llave:
| Tipo de petición | Límite |
|---|---|
Lecturas (GET) | 600 por minuto |
Escrituras (POST, PATCH, DELETE) | 60 por minuto |
Al excederlos recibes 429 RATE_LIMITED con un header Retry-After en segundos.
Respétalo y vuelve a encolar; no reintentes en un ciclo cerrado.
El límite de escritura es bajo a propósito: cada escritura aquí puede gastar un timbre, es decir, dinero.
Rotación y revocación
Las llaves no expiran solas. Desde Configuración → API Keys puedes ver la
fecha de último uso de cada una y revocarla; la revocación es inmediata y todas
las peticiones con esa llave pasan a responder 401 INVALID_API_KEY.
Para rotar sin cortar el servicio: crea la llave nueva, despliégala, confirma que
la vieja dejó de usarse (lastUsedAt deja de avanzar) y entonces revócala.
Higiene de la credencial
- Guárdala en variables de entorno o en un gestor de secretos — nunca en el repositorio ni en código de cliente.
- Nunca la mandes desde un navegador o una app móvil: cualquiera que abra las herramientas de desarrollo se la lleva. La llave vive en tu servidor.
- Una llave por integración y por ambiente. Así revocar una no tumba a las demás
y
lastUsedAtte dice de verdad quién sigue usando qué.