API estable v1

EtiQali API

Integra tu ERP con EtiQali para registrar albaranes de venta y generar trazabilidad alimentaria normativa automáticamente. Un único endpoint, REST sobre HTTPS, autenticación por clave.

Empezar en 3 pasos

Solicita acceso

Escribe a soporte@etiqali.com indicando el nombre de tu empresa, CIF y el ERP o software desde el que vas a integrar. Recibirás una clave de API personal y, opcionalmente, acceso al entorno de pruebas.

Configura tu ERP

Tu sistema debe poder realizar una llamada HTTPS POST con cuerpo JSON cada vez que se emita un albarán de venta. La mayoría de ERPs modernos lo soportan de forma nativa o mediante un script.

Envía tu primer albarán

Realiza una llamada al endpoint POST /api/v1/albara con los datos del albarán. EtiQali devuelve el número de lote único para cada línea, que puedes imprimir en el albarán físico junto al código QR para tus clientes.

Autenticación

Todas las peticiones a la API requieren una clave en la cabecera X-EtiQali-Key. Cada clave está autorizada para operar sobre un conjunto de empresas identificadas por CIF: una clave directa cubre una sola empresa (tu ERP emite lo tuyo); una clave de plataforma —una central de mercado, caja gremial o sistema que emite en nombre de varias empresas— cubre todo el conjunto que tiene autorizado. La regla es la misma en ambos casos: el cif_vendedor de cada albarán debe estar dentro del ámbito de la clave.

X-EtiQali-Key: etq_live_xxxxxxxxxxxxxxxxxxxxxxxx

Confidencialidad. Tu clave API identifica tu empresa frente a EtiQali. No la incluyas en código del lado del cliente, repositorios públicos o capturas de pantalla. Si crees que se ha visto comprometida, contacta inmediatamente con soporte para rotarla.

Entornos

EtiQali ofrece dos entornos. Ambos comparten la misma especificación de API. Las llamadas al entorno de pruebas no generan trazabilidad real ni etiquetas oficiales.

EntornoUsoBase URL
ProducciónDatos reales, etiquetas válidas legalmentehttps://api.etiqali.com
PruebasIntegración inicial y desarrolloFacilitado por soporte bajo petición

Registrar un albarán

Registra un albarán de venta en EtiQali y obtén el número de lote único asignado a cada línea. La llamada debe realizarse en el momento de emisión del albarán por parte del vendedor.

POST https://api.etiqali.com/api/v1/albara

Estructura de petición

El cuerpo de la petición debe ser un objeto JSON con los siguientes campos:

CampoTipoDescripción
num_albarastringREQIdentificador único del albarán dentro de tu numeración. Máximo 64 caracteres. Se usa como clave de idempotencia (ver sección Idempotencia).
datastringREQFecha del albarán en formato ISO 8601 (YYYY-MM-DD).
cif_vendedorstringREQCIF / NIF de la empresa vendedora. Debe estar autorizado para tu clave API (ver Autenticación).
cif_compradorstringREQCIF / NIF de la empresa compradora destinataria del albarán.
secciostringOPTSección de fresco del comprador, cuando el destinatario tiene una cuenta por sección (supermercados). Valores: "pesca", "carn", "fruta", "xarcuteria". Ver Compradores con secciones.
liniesarrayREQLíneas del albarán. Cada línea representa un producto o lote vendido. Mínimo 1, máximo 500 por llamada.

Campos de línea

Cada elemento del array linies describe un producto o lote vendido. Los campos opcionales aplican a sectores regulados específicamente (pesca, carne, etc.).

Campos comunes

CampoTipoDescripción
productestringREQNombre comercial del producto.
quantitatnumberREQCantidad vendida, en la unidad especificada en unitat.
secciostringOPTSección de fresco a la que va esta línea. Solo si el albarán mezcla secciones; prevalece sobre el seccio del albarán.
cod_artstringOPTCódigo de artículo en tu ERP. Muy recomendado para mantener la coherencia entre tu inventario y EtiQali.
lotstringOPTLote de trazabilidad del vendedor para esta línea. Muy recomendado: es lo que permite enlazar el recorrido del producto hacia atrás y hacia adelante en la cadena.
unitatstringOPTUnidad de medida. Valores: "kg", "ud", "caja", "l". Por defecto: "kg".
data_caducitatstringOPTFecha de caducidad o consumo preferente en formato YYYY-MM-DD.
conservaciostringOPTCondiciones de conservación. Ej: "Refrigerado 0–4 °C".
pais_origenstringOPTPaís de origen. Solo para acuicultura o producto transformado. En pescado salvaje no aplica: el origen es la zona de captura (zona_fao), conforme al Reglamento UE 1379/2013.

Campos pesca (Reglamento UE 1379/2013)

CampoTipoDescripción
nom_cientificstringOPTNombre científico en latín. Ej: "Merluccius merluccius".
zona_faostringOPTZona de captura FAO. Ej: "27" (Atlántico NE), "34" (Atlántico CE), "37" (Mediterráneo).
metode_producciostringOPTMétodo de producción (Reg. UE 1379/2013 art. 35b). Valores: "Captura" (salvaje) o "Acuicultura" (cría).
art_pescastringOPTArte de pesca (Reg. UE 1379/2013 art. 35c). Ej: "Arrastre de fondo", "Palangre de superficie", "Redes de enmalle".
llotjastringOPTLonja o puerto de desembarque.
barco_nomstringOPTNombre del buque pesquero.
barco_matriculastringOPTMatrícula oficial del buque.
data_capturastringOPTFecha de captura en formato YYYY-MM-DD.
estatstringOPTEstado de conservación. Valores: "Fresc", "Congelat", "Descongelat".

Campos carne (RD 1698/2003, RD 142/2026)

CampoTipoDescripción
especiestringOPTEspecie animal. Ej: "Vacuno", "Porcino", "Ovino".
pais_nacimientostringOPTPaís de nacimiento del animal.
pais_engordestringOPTPaís de cría / engorde.
pais_sacrificiostringOPTPaís del matadero.
matadero_idstringOPTNúmero de autorización del matadero.
despiece_idstringOPTNúmero de autorización de la sala de despiece.
lote_sacrificiostringOPTLote de sacrificio asignado por el matadero.

Respuesta

Una respuesta exitosa devuelve HTTP 200 con un objeto JSON que confirma el registro y devuelve los números de lote generados.

{
  "ok": true,
  "num_albara": "ALB-2026-001234",
  "lots": [
    {
      "producte": "Merluza europea",
      "num_lot": "ALB-2026-001234-1",
      "qr_url": "https://app.etiqali.com/lot.html?lot=ALB-2026-001234-1"
    }
  ]
}

Campos de respuesta

CampoTipoDescripción
okbooleantrue si el albarán se ha procesado correctamente.
num_albarastringConfirmación del identificador enviado.
lotsarrayLotes generados, uno por línea, en el mismo orden que las líneas enviadas.
lots[].num_lotstringNúmero de lote único generado por EtiQali. Debe imprimirse en el albarán físico junto al producto.
lots[].qr_urlstringURL pública del código QR de trazabilidad. Cualquier consumidor con esta URL puede ver los datos públicos del lote.

Imprime el num_lot en el albarán físico. El comprador y el consumidor final pueden escanear el QR derivado para acceder a la información de trazabilidad.

Compradores con secciones

Un supermercado tiene una cuenta de EtiQali por cada sección de fresco — pescadería, carnicería, frutería, charcutería — porque cada una lleva su propia trazabilidad, sus propios lotes y su propia cartelería. Todas comparten el mismo CIF de la sociedad.

Si envías solo el cif_comprador, el albarán entra en la sección predeterminada. Para dirigirlo a la que corresponde, añade seccio:

ValorSección
"pesca"Pescadería
"carn"Carnicería
"fruta"Frutería
"xarcuteria"Charcutería

Lo normal es enviarlo a nivel de albarán, porque un albarán suele ser de una sola sección. Si un albarán mezcla productos de varias, cada línea puede llevar su propio seccio, que prevalece sobre el del albarán:

{
  "num_albara": "A-1234",
  "data": "2026-09-01",
  "cif_vendedor": "B00000001",
  "cif_comprador": "B00000002",
  "seccio": "carn",
  "linies": [
    { "producte": "Solomillo de ternera", "cod_art": "512", "quantitat": 8 },
    { "producte": "Merluza", "cod_art": "235", "quantitat": 12, "seccio": "pesca" }
  ]
}

La respuesta incluye seccions con las secciones a las que ha ido el albarán, para que puedas verificar el encaminamiento desde tu ERP.

Compatibilidad. El campo es opcional. Si no lo envías, el comportamiento es el de siempre: el albarán se asigna a la empresa del CIF exacto. Las integraciones existentes no requieren ningún cambio.

Si el comprador no tiene secciones —una pescadería, un restaurante, un mayorista— el campo se ignora. No hace falta condicionarlo en tu código: puedes enviarlo siempre.

Idempotencia y rectificaciones

El campo num_albara actúa como clave de idempotencia. Puedes reenviar el mismo albarán múltiples veces sin riesgo de duplicación:

  • Mismo albarán, mismas líneas: EtiQali devuelve la respuesta original sin reprocesar. Útil para reintentos en caso de error de red.
  • Mismo albarán, líneas distintas: EtiQali interpreta que se trata de una rectificación y actualiza el contenido manteniendo el identificador.

Si tu ERP emite un albarán y posteriormente modifica las cantidades, basta con reenviar la llamada con el mismo num_albara. No necesitas eliminar ni anular el registro previo.

Ejemplo básico

Ejemplo mínimo en tres lenguajes:

curl -X POST https://api.etiqali.com/api/v1/albara \
  -H "Content-Type: application/json" \
  -H "X-EtiQali-Key: etq_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -d '{
    "num_albara": "ALB-2026-001234",
    "data": "2026-06-24",
    "cif_vendedor": "B00000001",
    "cif_comprador": "B00000002",
    "linies": [
      { "producte": "Merluza europea", "cod_art": "MER-EUR-1", "quantitat": 12.5 }
    ]
  }'
const response = await fetch('https://api.etiqali.com/api/v1/albara', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-EtiQali-Key': 'etq_live_xxxxxxxxxxxxxxxxxxxxxxxx'
  },
  body: JSON.stringify({
    num_albara: 'ALB-2026-001234',
    data: '2026-06-24',
    cif_vendedor: 'B00000001',
    cif_comprador: 'B00000002',
    linies: [
      { producte: 'Merluza europea', cod_art: 'MER-EUR-1', quantitat: 12.5 }
    ]
  })
});
const data = await response.json();
// data.lots[0].num_lot → imprimir en el albarán físico
import requests

response = requests.post(
    "https://api.etiqali.com/api/v1/albara",
    headers={
        "Content-Type": "application/json",
        "X-EtiQali-Key": "etq_live_xxxxxxxxxxxxxxxxxxxxxxxx",
    },
    json={
        "num_albara": "ALB-2026-001234",
        "data": "2026-06-24",
        "cif_vendedor": "B00000001",
        "cif_comprador": "B00000002",
        "linies": [
            {"producte": "Merluza europea", "cod_art": "MER-EUR-1", "quantitat": 12.5}
        ],
    },
)
data = response.json()
# data["lots"][0]["num_lot"] → imprimir en el albarán físico
$ch = curl_init('https://api.etiqali.com/api/v1/albara');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'X-EtiQali-Key: etq_live_xxxxxxxxxxxxxxxxxxxxxxxx',
    ],
    CURLOPT_POSTFIELDS     => json_encode([
        'num_albara'    => 'ALB-2026-001234',
        'data'          => '2026-06-24',
        'cif_vendedor'  => 'B00000001',
        'cif_comprador' => 'B00000002',
        'linies'        => [
            ['producte' => 'Merluza europea', 'cod_art' => 'MER-EUR-1', 'quantitat' => 12.5],
        ],
    ]),
]);
$data = json_decode(curl_exec($ch), true);
// $data['lots'][0]['num_lot'] → imprimir en el albarán físico

Ejemplo sector pesquero

Albarán completo con campos normativos según Reglamento UE 1379/2013:

{
  "num_albara": "ALB-2026-001235",
  "data": "2026-06-24",
  "cif_vendedor": "B00000001",
  "cif_comprador": "B00000002",
  "linies": [{
    "producte": "Merluza europea",
    "cod_art": "MER-EUR-1",
    "lot": "LL-2026-00871",
    "nom_cientific": "Merluccius merluccius",
    "quantitat": 18.5,
    "unitat": "kg",
    "zona_fao": "27",
    "metode_produccio": "Captura",
    "art_pesca": "Arrastre de fondo",
    "llotja": "Vigo",
    "barco_nom": "Nuevo Galicia",
    "barco_matricula": "3-VI-2-1-08",
    "data_captura": "2026-06-22",
    "estat": "Fresc",
    "conservacio": "0–4 °C",
    "data_caducitat": "2026-06-28"
  }]
}

Ejemplo sector cárnico

Albarán completo con campos normativos según RD 1698/2003 y RD 142/2026:

{
  "num_albara": "ALB-2026-001236",
  "data": "2026-06-24",
  "cif_vendedor": "B00000001",
  "cif_comprador": "B00000002",
  "linies": [{
    "producte": "Jarrete Vacuno Añojo",
    "cod_art": "JAR-VAC-1",
    "quantitat": 8.2,
    "unitat": "kg",
    "especie": "Vacuno",
    "pais_nacimiento": "España",
    "pais_engorde": "España",
    "pais_sacrificio": "España",
    "matadero_id": "ES10.00001/B",
    "despiece_id": "ES10.00002/B",
    "lote_sacrificio": "S-26-06-001",
    "conservacio": "Refrigerado 0–4 °C",
    "data_caducitat": "2026-07-01"
  }]
}

Códigos de error

La API utiliza códigos de estado HTTP estándar. En caso de error, la respuesta incluye un objeto JSON con detalle:

{
  "ok": false,
  "error": "Campos obligatorios manquen",
  "detail": "Falta el campo cif_comprador"
}
HTTPCausaAcción recomendada
400Cuerpo JSON inválido o faltan campos obligatorios.Revisar la estructura de la petición. Validar contra esta documentación.
401Clave API ausente o inválida.Verificar la cabecera X-EtiQali-Key. Solicitar nueva clave si la actual está revocada.
403El cif_vendedor no corresponde a tu clave API.Verificar que el CIF enviado coincide con el de tu empresa.
429Has superado el límite de peticiones por minuto de tu clave API.Espaciar las llamadas y reintentar tras unos segundos. Respeta la cabecera Retry-After si está presente.
500Error interno del servidor.Reintentar con espera exponencial: 1s, 2s, 4s, 8s. Si persiste, contactar con soporte.

Límites de uso

Para garantizar el servicio a todos los integradores, la API aplica límites razonables:

RecursoLímite
Peticiones por minuto y clave API600
Líneas por albarán500
Tamaño máximo del cuerpo1 MB
Tiempo máximo de respuesta30 segundos

Si tu volumen previsto supera estos límites, contacta con soporte para revisar una configuración a medida.

Buenas prácticas

  • Envía el albarán en el momento de emisión. Cuanto antes se registre, antes está disponible la trazabilidad para tu comprador.
  • Usa siempre cod_art. Mantener el código de artículo de tu ERP en cada línea facilita el cruce posterior y la generación de etiquetas coherentes.
  • Implementa reintentos. Para errores 5xx usa espera exponencial. Para 4xx no reintentes: revisa la petición.
  • Guarda el num_lot devuelto. Es el identificador que vincula tu albarán físico con la trazabilidad de EtiQali.
  • Trata la clave API como una contraseña. Almacénala en variables de entorno o un gestor de secretos, nunca en código fuente.

Versionado

La versión está incluida en la URL del endpoint (/api/v1/...). Cualquier cambio que rompa la compatibilidad dará lugar a una nueva versión (/api/v2/...) manteniendo la versión anterior durante al menos 12 meses.

Los cambios compatibles con la versión actual (nuevos campos opcionales, nuevos códigos de error) se introducen sin cambio de versión. Te recomendamos ignorar campos desconocidos en las respuestas.

Soporte para integradores

Para solicitar acceso, abrir una incidencia o consultar el estado del servicio:

Emailsoporte@etiqali.com
Tiempo de respuestaMenos de 24 horas laborables
Entorno de pruebasDisponible bajo petición
Acompañamiento técnicoIncluido en el plan Enterprise