Core concepts
Connection and webhook setup
Ping, set the webhook URL, read it, rotate the signing secret.
6.1 GET /ping
JSON
{
"connectionId": "pc_3f1c0a9e5b7d2c4f6a81",
"name": "Test-Partner A",
"storeName": "Pizzeria Roma",
"storeStatus": "online",
"webhookConfigured": true,
"menuUrl": "https://cdn.horeca-24.de/partner-api/menus/pc_3f1c0a9e5b7d2c4f6a81/menu.json",
"menuHash": "9b2f…",
"menuUpdatedAt": "2026-10-15T09:58:12.000Z"
}| Field | Meaning |
|---|---|
name | The name the restaurant gave the connection. Orders appear in the till under it. |
storeName | The restaurant's name, or null. |
storeStatus | online while the restaurant takes orders through this connection, else offline. |
webhookConfigured | Whether a webhook URL is set. Orders need one. |
menuUrl, menuHash, menuUpdatedAt | The menu file, the SHA-256 (hex) of its current bytes, and when it was last written. All null until the restaurant first syncs its menu. |
6.2 PUT /webhook
JSON
{ "url": "https://partner.example/hooks/horeca24" }The URL must:
- use
httpson port 443, with nouser:pass@part, and be at most 2048 characters long; - name a host (no IP literal, no
localhost) whose addresses are all public. Private, loopback, link-local, CGNAT, multicast, reserved and documentation ranges are refused.
We repeat this check at every delivery. A refused URL answers 422 INVALID_FIELD with path: "url".
Answer:
JSON
{ "url": "https://partner.example/hooks/horeca24", "webhookSecret": "whsec_…", "menuDelivery": "sent" }webhookSecretcomes only the first time a URL is set. Store it. If you lose it, callrotate-secret.- Setting the URL for the first time, or changing it, sends you
menu.updatedright away (if the restaurant has synced a menu).menuDeliverysays how that went:sent,queued(it will be retried),failedorskipped(nothing to send).
Until a webhook URL is set, no events are produced and orders are refused with 409 WEBHOOK_NOT_CONFIGURED.
6.3 GET /webhook
JSON
{ "url": "https://partner.example/hooks/horeca24", "configured": true,
"secrets": [ { "createdAt": "2026-10-15T09:00:00.000Z" } ] }This lists the dates of the active secrets, never the secrets themselves. A secret that is about to expire carries an expiresAt.
6.4 POST /webhook/rotate-secret
JSON
{ "webhookSecret": "whsec_…", "previousExpiresAt": "2026-10-16T09:00:00.000Z" }The new secret is shown once. The previous one keeps signing for 24 hours, so during that time each delivery carries two signatures (see §10.2). If rotations collide, you may get 409 REQUEST_IN_PROGRESS with Retry-After: 2. Retry then.