Naar de inhoud
Nieuw VERI*FACTU komt in 2027 en elpizzero is er al klaar voor. Ontdek hoe Even praten?Partners: para agencias
API Export Alleen-lezen · api@elpizzero.com

API Export

Alleen-lezen REST-API om de gegevens van je elpizzero-account —bestellingen, menukaart, zones, restaurant en statistieken— te exporteren naar je eigen systemen (CRM, BI, boekhouding, schermen, enz.). Inclusief een live stream (SSE) en uitgaande webhooks om in realtime op wijzigingen te reageren.

Bereik. Deze API maakt of wijzigt geen bestellingen. Het inladen van bestellingen in elpizzero is niet openbaar en wordt hier niet gedocumenteerd: het wordt per account geactiveerd, na validatie. Heb je zoiets nodig, schrijf ons dan op api@elpizzero.com.

Authenticatie

Bearer token in de header. Tokens hebben het formaat elp_live_<32hex> of elp_test_<32hex>.

Authorization: Bearer elp_live_3b8f0c2a1d4e5f6079a8b7c6d5e4f3a2

Maak tokens aan en trek ze in via Dashboard → Integraties → API-sleutels, waarbij je hun rechten kiest. Het token wordt maar één keer volledig getoond.

Rechten

ScopeActiveert
pedidos.leer/pedidos, /pedidos/{id}, /pedidos/{id}/historial, /resumen
carta.leer/carta
restaurante.leer/restaurante, /zonas
stream.escuchar/stream (SSE)
webhook.recibir/webhooks (aanmaken/verwijderen/lijst)

Token zonder de vereiste scope → 403 alcance_insuficiente.

Omgevingen

elp_live_ en elp_test_ lezen dezelfde echte gegevens; er is geen sandbox met gesimuleerde data. Het voorvoegsel is slechts een label om je tokens uit elkaar te houden.

Rate limit

60 req/min per token. Headers bij elk antwoord: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. Bij overschrijding → 429 + Retry-After.

Conventies

Fouten

Uniforme body + consistente 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 (bevat valores_validos)
404no_encontrado
405 / 429metodo_invalido · limite_alcanzado

Bestellingen opvragen

GET /pedidos

Bestellingen van het restaurant, aflopend gesorteerd op id, cursorpaginering.

QueryTipoBeschrijving
estadocsvpendienteconfirmadoen_preparacionlistoen_repartoentregadocancelado
tipoenumrepartorecogidamesa
desde / hastaISOBereik op creado_en (desde ≤ x < hasta).
limiteint1–100, standaard 25.
cursorstringWaarde van paginacion.siguiente van de vorige pagina.
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 }
}
Itereer met cursor = paginacion.siguiente tot het null is om de volledige geschiedenis op te halen.

Eén bestelling ophalen

GET /pedidos/{id}

Geeft het Bestelobject terug. {id} met voorvoegsel, bijv. ped_ni. 404 no_encontrado als het niet van jou is.

Geschiedenis van een bestelling

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

Menukaart

GET /carta

Volledige boom categorieën → producten → maten → optiegroepen → opties. ?solo_disponibles=true sluit verborgen/uitverkochte items uit.

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

Bezorggebieden

GET /zonas

Zones met polygoon in GeoJSON (coördinaten [lng, lat], gesloten 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

Restaurantgegevens: contact, locatie, openingstijden per dag, branding, talen per kanaal, reputatie. Zonder gevoelige fiscale gegevens.

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

Samenvatting / statistieken

GET /resumen?periodo=30d

periodo ∈ hoyayer7d30dmes_actual. Berekend in de tijdzone van het restaurant; sluit geannuleerde/geweigerde bestellingen uit.

{
  "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. Pusht events direct. Auth via query (EventSource ondersteunt geen headers). Native herverbinding elke 5 min via Last-Event-ID; conexion.ping elke ~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);
});

Optioneel filter ?eventos=pedido.nuevo,pedido.aceptado. Verzonden typen:

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

Uitgaande webhooks

Alternatief pull → push: wij sturen een POST naar je URL wanneer een bestelling verandert. Alleen uitgaand.

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 }

Events: die van de stream + jokertekens pedido.* en *.  GET /webhooks toont lijst · DEL /webhooks/{id} verwijdert.

Aflevering en handtekening

Elke aflevering bevat deze headers; de body is hetzelfde object als in de 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);
Bij een fout proberen we opnieuw (X-Elp-Intento loopt op). Ontdubbel op X-Elp-Id.

Bestelobject

Structuur die wordt teruggegeven door /pedidos, /pedidos/{id}, de stream en de webhooks. Klantgegevens zijn in het voorbeeld geanonimiseerd. direccion/mesa/entrega/fiscal zijn null wanneer ze niet van toepassing zijn.

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

Voorbeeld: keuken-tv-scherm

Zelfstandige HTML+JS (alleen-lezen): plak je token, open het op een tv en de bestellingen komen live binnen via de stream.

→ Voorbeeld keuken-tv openen