Aller au contenu
Nouveau VERI*FACTU arrive en 2027 et elpizzero est déjà prêt. Découvrez comment On en parle ?Partners: para agencias
API Export Lecture seule · api@elpizzero.com

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.

Portée. Cette API ne crée ni ne modifie de commandes. L'ingestion de commandes vers elpizzero n'est pas publique et n'est pas documentée ici : elle est activée par compte, après validation. Si vous avez besoin d'une telle fonction, écrivez-nous à api@elpizzero.com.

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

ScopeActive
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

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"
}
HTTPcodigo
401llave_ausente · llave_invalida · llave_revocada · llave_expirada
403alcance_insuficiente · restaurante_inactivo
400parametro_invalido (inclut valores_validos)
404no_encontrado
405 / 429metodo_invalido · limite_alcanzado

Lister les commandes

GET /pedidos

Commandes du restaurant, ordre id décroissant, pagination par curseur.

QueryTipoDescription
estadocsvpendienteconfirmadoen_preparacionlistoen_repartoentregadocancelado
tipoenumrepartorecogidamesa
desde / hastaISOPlage sur creado_en (desde ≤ x < hasta).
limiteint1–100, 25 par défaut.
cursorstringValeur 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 }
}
Itérez avec cursor = paginacion.siguiente jusqu'à ce qu'il soit null pour extraire tout l'historique.

Obtenir une commande

GET /pedidos/{id}

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

GET /pedidos/{id}/historial
{
  "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

GET /carta

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

GET /zonas

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

GET /restaurante

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

GET /resumen?periodo=30d

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)

GET /stream

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.

POST /webhooks
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);
Nous réessayons en cas d'échec (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.

→ Ouvrir l'exemple TV cuisine