
API Export
elpizzero 계정의 데이터(주문, 메뉴, 배달 구역, 레스토랑 정보, 지표)를 CRM, BI, 회계, 디스플레이 등 자체 시스템으로 내보내기 위한 읽기 전용 REST API입니다. 변경 사항에 실시간으로 대응할 수 있도록 라이브 스트림(SSE)과 발신 webhook을 제공합니다.
- Base URL:
https://elpizzero.com/api/export - 인증: 요청마다
Authorization: Bearer <token>을 사용합니다. - 형식: JSON UTF-8. 금액은 정수 센트 단위, 날짜는 ISO-8601 UTC입니다.
- 메서드: 모든 리소스에서
GET을 사용하며,POST/DELETE는 webhook 관리에만 사용합니다.
인증
헤더를 통한 Bearer token. token 형식은 elp_live_<32hex> 또는 elp_test_<32hex>입니다.
Authorization: Bearer elp_live_3b8f0c2a1d4e5f6079a8b7c6d5e4f3a2
token은 패널 → 연동 → API 키에서 권한을 선택하여 생성하고 폐기합니다. token은 단 한 번만 전체가 표시됩니다.
권한
| Scope | 활성화되는 기능 |
|---|---|
pedidos.leer | /pedidos, /pedidos/{id}, /pedidos/{id}/historial, /resumen |
carta.leer | /carta |
restaurante.leer | /restaurante, /zonas |
stream.escuchar | /stream (SSE) |
webhook.recibir | /webhooks (등록/삭제/목록) |
필요한 스코프가 없는 token → 403 alcance_insuficiente.
환경
elp_live_와 elp_test_는 동일한 실제 데이터를 읽습니다. 모의 데이터가 있는 샌드박스는 없습니다. 접두사는 token을 구분하기 위한 라벨일 뿐입니다.
Rate limit
token당 분당 60회 요청. 모든 응답에 다음 헤더가 포함됩니다: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. 초과 시 → 429 + Retry-After.
규칙
- 금액: 정수 센트 단위(
total_cents: 820= 8,20 €). 통화는 별도 필드로 제공됩니다(moneda: "EUR"). - 날짜:
Z가 붙은 ISO-8601 UTC(2026-05-31T20:42:15Z). - ID: 유형 접두사가 붙은 불투명 값 —
ped_,prod_,cat_,tam_,grp_,opt_,zon_,rest_,itm_,wh_. 문자열로 취급하세요. - 격리: 각 token은 하나의 레스토랑에 연결되며 해당 레스토랑의 데이터만 반환합니다.
- 페이지네이션: cursor 방식(
cursor→paginacion.siguiente), 기본 정렬은 내림차순입니다.
오류
일관된 본문 + 일관된 HTTP 코드:
{
"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 (valores_validos 포함) |
| 404 | no_encontrado |
| 405 / 429 | metodo_invalido · limite_alcanzado |
주문 목록
레스토랑의 주문을 id 내림차순으로 반환하며, cursor 페이지네이션을 사용합니다.
| Query | Tipo | 설명 |
|---|---|---|
estado | csv | pendienteconfirmadoen_preparacionlistoen_repartoentregadocancelado |
tipo | enum | repartorecogidamesa |
desde / hasta | ISO | creado_en 기준 범위(desde ≤ x < hasta). |
limite | int | 1–100, 기본값 25. |
cursor | string | 이전 페이지의 paginacion.siguiente 값. |
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로 null이 될 때까지 반복하세요.주문 조회
주문 객체를 반환합니다. {id}는 접두사가 붙은 ID입니다(예: ped_ni). 본인의 주문이 아니면 404 no_encontrado.
주문 이력
{
"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":{} }
]
}
메뉴
카테고리 → 상품 → 사이즈 → 옵션 그룹 → 옵션으로 이어지는 전체 트리. ?solo_disponibles=true를 사용하면 숨김/품절 항목이 제외됩니다.
{
"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 }] }]
}]
}]
}
배달 구역
GeoJSON 폴리곤으로 된 배달 구역(좌표는 [lng, lat], 닫힌 링).
{ "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], /* … */]] }
}] }
레스토랑
레스토랑 정보: 연락처, 위치, 요일별 영업시간, 브랜딩, 채널별 언어, 평판. 민감한 세무 정보는 포함되지 않습니다.
{
"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 }
}
요약 / 지표
periodo ∈ hoyayer7d30dmes_actual. 레스토랑의 시간대 기준으로 계산되며 취소/거부된 주문은 제외됩니다.
{
"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 }]
}
라이브 스트림(SSE)
Server-Sent Events. 이벤트를 즉시 푸시합니다. 인증은 쿼리로 합니다(EventSource는 헤더를 지원하지 않음). 5분마다 Last-Event-ID를 통한 기본 재연결이 이루어지며, conexion.ping은 약 25초마다 전송됩니다.
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);
});
선택적 필터 ?eventos=pedido.nuevo,pedido.aceptado. 발생하는 이벤트 유형:
pedido.nuevopedido.aceptadopedido.rechazadopedido.estado_cambiadopedido.item_modificadopedido.entregadopedido.cancelado
발신 webhook
pull에서 push로의 대안: 주문이 변경되면 지정한 URL로 POST를 보냅니다. 발신 전용입니다.
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 }
이벤트: 스트림의 이벤트 + 와일드카드 pedido.* 및 *. GET /webhooks 목록 · DEL /webhooks/{id} 삭제.
전달 및 서명
모든 전송에는 다음 헤더가 포함되며, 본문은 스트림의 객체와 동일합니다:
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가 증가). X-Elp-Id로 중복을 제거하세요.주문 객체
/pedidos, /pedidos/{id}, 스트림 및 webhook이 반환하는 구조입니다. 예제의 고객 데이터는 익명 처리되었습니다. direccion/mesa/entrega/fiscal은 해당되지 않을 때 null입니다.
{
"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
}
예제: 주방 TV 화면
독립 실행형 HTML+JS(읽기 전용): token을 붙여넣고 TV에서 열면 스트림을 통해 주문이 실시간으로 들어옵니다.