
API Export
API REST en lecture seule pour exporter les données de votre compte elpizzero —commandes, carte, zones, restaurant et métriques— vers vos propres systèmes (CRM, BI, comptabilité, écrans, etc.). Elle inclut un flux en direct (SSE) et des webhooks sortants pour réagir aux changements en temps réel.
- Base URL :
https://elpizzero.com/api/export - Auth :
Authorization: Bearer <token>à chaque requête. - Format : JSON UTF-8. Montants en centimes entiers, dates en ISO-8601 UTC.
- Méthodes :
GETsur toutes les ressources ;POST/DELETEuniquement pour gérer vos webhooks.
Authentification
Bearer token dans l'en-tête. Les tokens ont le format elp_live_<32hex> ou elp_test_<32hex>.
Authorization: Bearer elp_live_3b8f0c2a1d4e5f6079a8b7c6d5e4f3a2
Générez et révoquez vos tokens dans Panneau → Intégrations → Clés d'API, en choisissant leurs permissions. Le token n'est affiché en entier qu'une seule fois.
Permissions
| Scope | Active |
|---|---|
pedidos.leer | /pedidos, /pedidos/{id}, /pedidos/{id}/historial, /resumen |
carta.leer | /carta |
restaurante.leer | /restaurante, /zonas |
stream.escuchar | /stream (SSE) |
webhook.recibir | /webhooks (création/suppression/liste) |
Token sans le scope requis → 403 alcance_insuficiente.
Environnements
elp_live_ et elp_test_ lisent les mêmes données réelles ; il n'y a pas de sandbox avec des données simulées. Le préfixe n'est qu'une étiquette pour distinguer vos tokens.
Rate limit
60 req/min par token. En-têtes dans chaque réponse : X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. En cas de dépassement → 429 + Retry-After.
Conventions
- Argent : centimes entiers (
total_cents: 820= 8,20 €). Devise dans un champ à part (moneda: "EUR"). - Dates : ISO-8601 UTC avec
Z(2026-05-31T20:42:15Z). - IDs : opaques, avec un préfixe de type —
ped_,prod_,cat_,tam_,grp_,opt_,zon_,rest_,itm_,wh_. Traitez-les comme des chaînes. - Isolation : chaque token est lié à un restaurant ; il ne renvoie que ses données.
- Pagination : par curseur (
cursor→paginacion.siguiente), ordre décroissant par défaut.
Erreurs
Corps uniforme + code HTTP cohérent :
{
"ok": false,
"error": "Esta llave no tiene el alcance necesario: pedidos.leer",
"codigo": "alcance_insuficiente",
"doc": "https://elpizzero.com/docs/api/export#auth"
}
| HTTP | codigo |
|---|---|
| 401 | llave_ausente · llave_invalida · llave_revocada · llave_expirada |
| 403 | alcance_insuficiente · restaurante_inactivo |
| 400 | parametro_invalido (inclut valores_validos) |
| 404 | no_encontrado |
| 405 / 429 | metodo_invalido · limite_alcanzado |
Lister les commandes
Commandes du restaurant, ordre id décroissant, pagination par curseur.
| Query | Tipo | Description |
|---|---|---|
estado | csv | pendienteconfirmadoen_preparacionlistoen_repartoentregadocancelado |
tipo | enum | repartorecogidamesa |
desde / hasta | ISO | Plage sur creado_en (desde ≤ x < hasta). |
limite | int | 1–100, 25 par défaut. |
cursor | string | Valeur de paginacion.siguiente de la page précédente. |
curl "https://elpizzero.com/api/export/pedidos?estado=entregado&desde=2026-05-01&limite=50" \
-H "Authorization: Bearer elp_live_..."
{
"datos": [ /* Objeto Pedido */ ],
"paginacion": { "limite":50, "siguiente":"ni", "anterior":null, "total_aprox":494 }
}
cursor = paginacion.siguiente jusqu'à ce qu'il soit null pour extraire tout l'historique.Obtenir une commande
Renvoie l'Objet Commande. {id} avec préfixe, p. ex. ped_ni. 404 no_encontrado si elle n'est pas à vous.
Historique d'une commande
{
"pedido_id": "ped_ni",
"eventos": [
{ "momento":"2026-05-31T20:42:15Z", "accion":"order_created",
"origen":"sistema", // sistema|panel|tpv|apk_recepcion|api
"usuario":null, "detalle":{} }
]
}
Carte
Arbre complet catégories → produits → tailles → groupes d'options → options. ?solo_disponibles=true exclut ce qui est masqué/épuisé.
{
"restaurante_id":"rest_1", "restaurante_slug":"tu-restaurante",
"moneda":"EUR", "idioma_origen":"es", "generado_en":"2026-06-01T18:41:27Z",
"categorias": [{
"id":"cat_v", "nombre":"Pizzas", "activa":true,
"visible_dias":["lun","mar","mie","jue","vie","sab","dom"], "visible_horario":null,
"productos": [{
"id":"prod_3J", "nombre":"Margarita", "precio_cents":680,
"disponible":true, "destacado":false, "alergenos":["gluten","lacteos"],
"tamaños":[{ "id":"tam_11", "nombre":"mediana", "precio_cents":680, "predeterminado":true }],
"grupos_opcion":[{ "id":"grp_73", "nombre":"Extras", "requerido":false,
"min_seleccion":0, "max_seleccion":5,
"opciones":[{ "id":"opt_8", "nombre":"Extra queso", "precio_cents":120 }] }]
}]
}]
}
Zones de livraison
Zones avec polygone en GeoJSON (coordonnées [lng, lat], anneau fermé).
{ "datos": [{
"id":"zon_8", "nombre":"Albatera", "slug":"albatera",
"color":"#44c3e5", "tarifa_cents":250, "pedido_minimo_cents":2000,
"minutos_estimados":40, "activa":true,
"poligono":{ "tipo":"Polygon", "coordenadas":[[[-0.872,38.186], /* … */]] }
}] }
Restaurant
Fiche du restaurant : contact, localisation, horaires par jour, branding, langues par canal, réputation. Sans données fiscales sensibles.
{
"id":"rest_1", "slug":"tu-restaurante", "nombre":"Tu Restaurante",
"moneda":"EUR", "zona_horaria":"Europe/Madrid",
"acepta_pedidos":true, "pedido_minimo_cents":500,
"horario":{ "viernes":[{"desde":"18:45","hasta":"23:30"}] /* … */ },
"contacto":{ "email":"…", "telefono":"…", "web":"…" },
"ubicacion":{ "direccion":"…", "ciudad":"…", "lat":38.14, "lng":-0.88 },
"branding":{ "logo_url":"…", "color_primario":"…", "galeria":[] },
"reputacion":{ "puntuacion":4.7, "votos":128 }
}
Résumé / métriques
periodo ∈ hoyayer7d30dmes_actual. Calculé dans le fuseau horaire du restaurant ; exclut les commandes annulées/refusées.
{
"periodo":"30d", "desde":"2026-05-03T00:00:00+02:00", "hasta":"2026-06-02T00:00:00+02:00",
"zona_horaria":"Europe/Madrid",
"kpis":{ "pedidos_total":442, "pedidos_cancelados":52, "clientes_distintos":413,
"ventas_cents":893435, "ticket_medio_cents":2021, "moneda":"EUR" },
"mix_tipo":{ "reparto":268, "recogida":171, "mesa":3 },
"top_productos":[{ "producto_id":"prod_3K", "nombre":"Margarita", "unidades":150, "ventas_cents":113845 }]
}
Flux en direct (SSE)
Server-Sent Events. Pousse les événements instantanément. Auth par query (EventSource ne gère pas les en-têtes). Reconnexion native toutes les 5 min via Last-Event-ID ; conexion.ping toutes les ~25 s.
const es = new EventSource("https://elpizzero.com/api/export/stream?llave=elp_live_...");
es.addEventListener("pedido.nuevo", e => {
const ev = JSON.parse(e.data); // ev.datos.pedido = Objeto Pedido
console.log(ev.datos.pedido.numero);
});
Filtre optionnel ?eventos=pedido.nuevo,pedido.aceptado. Types émis :
pedido.nuevopedido.aceptadopedido.rechazadopedido.estado_cambiadopedido.item_modificadopedido.entregadopedido.cancelado
Webhooks sortants
Alternative pull → push : nous envoyons un POST à votre URL lorsqu'une commande change. Sortant uniquement.
curl -X POST "https://elpizzero.com/api/export/webhooks" \
-H "Authorization: Bearer elp_live_..." -H "Content-Type: application/json" \
-d '{"url":"https://tu-sistema.com/hook","nombre":"Mi CRM","eventos":["pedido.aceptado","pedido.entregado"]}'
{ "id":"wh_3", "url":"https://tu-sistema.com/hook",
"eventos":["pedido.aceptado","pedido.entregado"],
"secreto_firma":"a1b2…(64 hex, se muestra UNA vez)", "activo":true }
Événements : ceux du flux + les jokers pedido.* et *. GET /webhooks liste · DEL /webhooks/{id} supprime.
Livraison et signature
Chaque envoi inclut ces en-têtes ; le corps est le même objet que dans le flux :
X-Elp-Evento: pedido.aceptado
X-Elp-Id: 84213 # úsalo como clave de idempotencia
X-Elp-Firma: <hmac_sha256_hex(secreto, cuerpo_crudo)>
X-Elp-Intento: 1
// Verificación (Node)
const firma = crypto.createHmac("sha256", SECRETO).update(rawBody).digest("hex");
if (firma !== req.headers["x-elp-firma"]) return res.sendStatus(401);
X-Elp-Intento s'incrémente). Dédoublonnez via X-Elp-Id.Objet Commande
Structure renvoyée par /pedidos, /pedidos/{id}, le flux et les webhooks. Données client anonymisées dans l'exemple. direccion/mesa/entrega/fiscal valent null lorsqu'ils ne s'appliquent pas.
{
"id":"ped_ni", "numero":"20260531-095",
"tipo":"reparto", // reparto|recogida|mesa
"estado":"en_preparacion",
"fuente":"web_publica", // web_publica|tpv|manual|admin
"creado_en":"2026-05-31T20:42:15Z", "aceptado_en":"…Z",
"entregado_en":null, "programado_para":null,
"restaurante":{ "id":"rest_1", "slug":"tu-restaurante", "nombre":"Tu Restaurante" },
"cliente":{ "nombre":"Juan Pérez", "telefono":"+34 600 000 000",
"email":"cliente@ejemplo.com", "consintio_marketing":false },
"direccion":{ "linea":"Calle Mayor 22", "codigo_postal":null, "pais":"ES", "lat":38.154, "lng":-0.880 },
"mesa":null,
"items":[{ "id":"itm_A3", "producto_id":"prod_3K", "nombre":"Margarita",
"tamaño":"mediana", "cantidad":1,
"precio_unitario_cents":720, "opciones_total_cents":120, "total_cents":840,
"estado_cocina":"pendiente",
"opciones":[{ "id":"opc_5", "grupo":"Extras", "nombre":"Extra queso", "cantidad":1, "precio_cents":120 }] }],
"totales":{ "moneda":"EUR", "subtotal_cents":840, "descuento_cents":0, "propina_cents":0,
"tarifa_reparto_cents":100, "impuestos_cents":85, "total_cents":1025,
"iva_desglose":[{ "tipo_porcentaje":10, "base_cents":940, "iva_cents":85 }] },
"pago":{ "metodo":"online", "estado":"pagado", "proveedor":"stripe",
"referencia_externa":"pi_3Td…", "pagos":[] },
"entrega":{ "repartidor_nombre":null, "zona_id":"zon_a", "zona_nombre":"Granja de Rocamora", "tarifa_cents":100 },
"fiscal":{ "factura_numero":"FA-1132/2026", "factura_fecha":"…Z", "factura_pdf":"https://…/factura.pdf" },
"instrucciones":null
}
Exemple : écran TV de cuisine
HTML+JS autonome (lecture seule) : collez votre token, ouvrez-le sur une TV et les commandes arrivent en direct via le flux.