Zum Inhalt springen
Neu VERI*FACTU kommt 2027 – elpizzero ist schon bereit. So geht’s Lass uns redenPartners: para agencias
API Export Nur lesend · api@elpizzero.com

API Export

Nur lesende REST-API, um die Daten Ihres elpizzero-Kontos —Bestellungen, Speisekarte, Zonen, Restaurant und Kennzahlen— in Ihre eigenen Systeme (CRM, BI, Buchhaltung, Displays usw.) zu exportieren. Enthält einen Live-Stream (SSE) und ausgehende Webhooks, um in Echtzeit auf Änderungen zu reagieren.

Umfang. Diese API erstellt oder ändert keine Bestellungen. Die Übernahme von Bestellungen in elpizzero ist nicht öffentlich und wird hier nicht dokumentiert: Sie wird pro Konto nach Prüfung freigeschaltet. Wenn Sie so etwas benötigen, schreiben Sie uns an api@elpizzero.com.

Authentifizierung

Bearer-Token im Header. Tokens haben das Format elp_live_<32hex> oder elp_test_<32hex>.

Authorization: Bearer elp_live_3b8f0c2a1d4e5f6079a8b7c6d5e4f3a2

Erstellen und widerrufen Sie Tokens unter Dashboard → Integrationen → API-Schlüssel und wählen Sie deren Berechtigungen. Das vollständige Token wird nur einmal angezeigt.

Berechtigungen

ScopeAktiviert
pedidos.leer/pedidos, /pedidos/{id}, /pedidos/{id}/historial, /resumen
carta.leer/carta
restaurante.leer/restaurante, /zonas
stream.escuchar/stream (SSE)
webhook.recibir/webhooks (anlegen/löschen/auflisten)

Token ohne den erforderlichen Scope → 403 alcance_insuficiente.

Umgebungen

elp_live_ und elp_test_ lesen dieselben echten Daten; es gibt keine Sandbox mit simulierten Daten. Das Präfix ist nur ein Label, damit Sie Ihre Tokens unterscheiden können.

Rate Limit

60 Anfragen/Min. pro Token. Header in jeder Antwort: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. Bei Überschreitung → 429 + Retry-After.

Konventionen

Fehler

Einheitlicher Body + konsistenter HTTP-Statuscode:

{
  "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 (enthält valores_validos)
404no_encontrado
405 / 429metodo_invalido · limite_alcanzado

Bestellungen auflisten

GET /pedidos

Bestellungen des Restaurants, nach id absteigend sortiert, Cursor-Paginierung.

QueryTipoBeschreibung
estadocsvpendienteconfirmadoen_preparacionlistoen_repartoentregadocancelado
tipoenumrepartorecogidamesa
desde / hastaISOBereich auf creado_en (desde ≤ x < hasta).
limiteint1–100, Standard 25.
cursorstringWert von paginacion.siguiente der vorherigen Seite.
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 }
}
Iterieren Sie mit cursor = paginacion.siguiente, bis der Wert null ist, um den gesamten Verlauf abzuziehen.

Eine Bestellung abrufen

GET /pedidos/{id}

Liefert das Bestellobjekt. {id} mit Präfix, z. B. ped_ni. 404 no_encontrado, wenn sie nicht Ihnen gehört.

Verlauf einer Bestellung

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":{} }
  ]
}

Speisekarte

GET /carta

Vollständiger Baum Kategorien → Produkte → Größen → Optionsgruppen → Optionen. ?solo_disponibles=true schließt Ausgeblendetes/Ausverkauftes aus.

{
  "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 }] }]
    }]
  }]
}

Liefergebiete

GET /zonas

Zonen mit Polygon als GeoJSON (Koordinaten [lng, lat], geschlossener Ring).

{ "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

Restaurantprofil: Kontakt, Standort, Öffnungszeiten pro Tag, Branding, Sprachen je Kanal, Reputation. Ohne sensible Steuerdaten.

{
  "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 }
}

Zusammenfassung / Kennzahlen

GET /resumen?periodo=30d

periodo ∈ hoyayer7d30dmes_actual. Berechnet in der Zeitzone des Restaurants; schließt stornierte/abgelehnte Bestellungen aus.

{
  "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 }]
}

Live-Stream (SSE)

GET /stream

Server-Sent Events. Überträgt Ereignisse sofort. Auth per Query (EventSource unterstützt keine Header). Native Wiederverbindung alle 5 Min. über Last-Event-ID; conexion.ping alle ca. 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);
});

Optionaler Filter ?eventos=pedido.nuevo,pedido.aceptado. Gesendete Typen:

pedido.nuevopedido.aceptadopedido.rechazadopedido.estado_cambiadopedido.item_modificadopedido.entregadopedido.cancelado

Ausgehende Webhooks

Alternative Pull → Push: Wir senden einen POST an Ihre URL, wenn sich eine Bestellung ändert. Nur ausgehend.

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 }

Ereignisse: die des Streams + die Platzhalter pedido.* und *.  GET /webhooks listet · DEL /webhooks/{id} löscht.

Zustellung und Signatur

Jede Zustellung enthält diese Header; der Body ist dasselbe Objekt wie im Stream:

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);
Bei Fehlern versuchen wir es erneut (X-Elp-Intento wird hochgezählt). Deduplizieren Sie über X-Elp-Id.

Bestellobjekt

Struktur, die von /pedidos, /pedidos/{id}, dem Stream und den Webhooks geliefert wird. Kundendaten im Beispiel anonymisiert. direccion/mesa/entrega/fiscal sind null, wenn sie nicht zutreffen.

{
  "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
}

Beispiel: Küchen-TV-Anzeige

Eigenständiges HTML+JS (nur lesend): Token einfügen, auf einem TV öffnen, und die Bestellungen kommen live über den Stream herein.

→ Beispiel Küchen-TV öffnen