Webhooks
Your POS reports order status to Swoop by posting a webhook to the adapter. This page
covers the endpoint, how your payload becomes a StatusEvent, and the acknowledgement
contract that controls redelivery.
Endpoint
POST /webhook/{integration}/{locationId}?token=YOUR_WEBHOOK_TOKEN
{integration}is your integration identifier, issued at onboarding;{locationId}is the Swoop club id the order belongs to.tokenauthenticates the delivery (see Authentication); a bad token returns401.- The body is read up to 1 MiB. All request headers are forwarded to your translator.
Translation
The adapter is fully provider-agnostic — no POS-specific strings live in the core. It
hands your raw webhook to your provider's WebhookTranslator:
TranslateWebhook(headers map[string]string, body []byte) (*canonical.StatusEvent, error)
Three outcomes:
| You return | Adapter does | HTTP |
|---|---|---|
a *StatusEvent |
applies it to the member's order (persist + live publish) | 200 (or 500 if applying fails transiently) |
nil, nil |
treats it as "not a status change I map" — ignores | 200 |
nil, err |
treats the payload as poison — drops it | 200 |
This is also where you verify any HMAC/signature header before trusting the body.
Acknowledgement & redelivery
The response status code is your POS's redelivery signal:
| Response | Meaning | Your POS should |
|---|---|---|
200 |
Accepted, or intentionally ignored/dropped | stop redelivering |
401 |
Bad/missing token | fix auth, resend |
500 |
Transient failure applying the status | redeliver |
The deliberate design choice: poison payloads are acked (200), not nacked. A webhook
the adapter can't parse will never be fixed by redelivery, so it's dropped rather than
looped forever. Only transient failures (e.g. a momentary write error) return 500 to
invite redelivery — and because status application is keyed on the Swoop order id,
redelivery is safe.
Example
A POS "order ready" webhook (illustrative shape):
POST /webhook/my-pos/51?token=••• HTTP/1.1
Content-Type: application/json
{
"eventType": "order.updated",
"order": { "thirdPartyReference": "128277", "status": "READY" }
}
Your translator maps this to:
{ "swoopOrderId": "128277", "status": "ready", "providerOrderId": "POS-55012" }
Swoop then moves the member's order to ready for pickup or ready for delivery based on the order's fulfillment.