Autenticacion API
La API de Zarela usa autenticacion por API key por ambiente. No hay login con usuario/contrasena ni intercambio de tokens Bearer para la integracion server-to-server: cada solicitud privada incluye el header X-API-KEY.
Diferencia clave
El header Authorization queda reservado para OAuth2/portal en versiones futuras. Para integracion de sistemas usa siempre X-API-KEY. No necesitas pedir un token ni renovarlo.
Encabezados requeridos
Todos los endpoints privados requieren:
X-API-KEY: {api_key_del_ambiente}
Content-Type: application/json
Accept: application/json
Ejemplo de solicitud autenticada
curl -X POST \
https://ecf.api.zarela.do/TesteCF/documentos-ecf/status/batch \
-H 'X-API-KEY: zk_test_...' \
-H 'Content-Type: application/json' \
-d '{ "encfs": ["E310000000010", "E340000000001"] }'
async function statusBatch(encfs) {
const response = await fetch(
"https://ecf.api.zarela.do/TesteCF/documentos-ecf/status/batch",
{
method: "POST",
headers: {
"X-API-KEY": process.env.ZARELA_API_KEY,
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({ encfs }),
}
);
return await response.json();
}
using System.Net.Http;
using System.Text;
public class ZarelaClient
{
private readonly HttpClient _client = new HttpClient();
private readonly string _apiKey;
public ZarelaClient(string apiKey) => _apiKey = apiKey;
public async Task<string> StatusBatch(string payloadJson)
{
_client.DefaultRequestHeaders.Clear();
_client.DefaultRequestHeaders.Add("X-API-KEY", _apiKey);
var content = new StringContent(payloadJson, Encoding.UTF8, "application/json");
var response = await _client.PostAsync(
"https://ecf.api.zarela.do/TesteCF/documentos-ecf/status/batch",
content);
return await response.Content.ReadAsStringAsync();
}
}
<?php
function statusBatch($payload, $apiKey) {
$ch = curl_init('https://ecf.api.zarela.do/TesteCF/documentos-ecf/status/batch');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-API-KEY: ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$result = curl_exec($ch);
curl_close($ch);
return json_decode($result, true);
}
Scopes
Cada API key se emite con un conjunto de scopes. La solicitud falla con 403 si la key no tiene el scope requerido por el endpoint.
| Scope | Uso | Endpoints |
|---|---|---|
ecf:validate | Pre-flight sin consumo fiscal | POST /{env}/documentos-ecf?validate=true |
ecf:create | Crear documentos e-CF | POST /{env}/documentos-ecf |
ecf:read | Scope reservado para consultas/artifacts habilitados | no requerido para status/batch |
status:read | Estado por lote | POST /{env}/documentos-ecf/status/batch |
tenant:admin | Operaciones administrativas | secuencias, anulaciones, certificacion, aprobacion comercial |
Manejo de errores de autenticacion
Zarela devuelve un cuerpo de error consistente:
{
"ok": false,
"error": {
"code": "INSUFFICIENT_SCOPE",
"message": "La API key no tiene el scope requerido."
},
"correlationId": "c0ffee00-1234-..."
}
| Codigo HTTP | Causa | Solucion |
|---|---|---|
401 | Falta la API key o es invalida | Verifica el header X-API-KEY y que la key este activa. |
403 | API key sin el scope requerido | Asigna el scope correcto a la key desde el portal. |
403 | Key de un ambiente usada en otro | Usa la key del ambiente correcto (TesteCF/CerteCF/eCF). |
Usa el correlationId
Guarda el correlationId de las respuestas de error: agiliza el soporte y el rastreo de incidencias.
Buenas practicas
- Almacenamiento seguro: guarda las API keys en un secret manager, nunca en codigo fuente ni repositorios.
- Una key por integracion: facilita la rotacion y la revocacion.
- Rotacion sin corte: crea la key nueva, actualiza el ERP/POS, confirma uso y luego revoca la anterior. En produccion las keys no expiran automaticamente salvo politica acordada.
- No registres keys completas en logs.
- Respeta el rate limiting segun tu plan; implementa backoff exponencial ante
429.