Skip to main content

Delivery and Retries

What Your Endpoint Must Do​

  • Answer with any 2xx status (for example 200 or 204) within 10 seconds. A 2xx means "received"; Mekari POS does not read your response body.
  • Verify the signature first (see Verifying Signatures), then save the event and answer. Do slow work, such as calling the API or updating other systems, later in a background job.
  • Answer every attempt the same way, also for an event you already received: answer 2xx and skip the work.

A delivery is one event sent to one endpoint. Each delivery is tried until it gets a 2xx or the rules below give up.

Retries​

AttemptSent about this long after the previous attempt failed
1Right away, when the event happens
230 seconds
32 minutes
410 minutes
530 minutes
61 hour
73 hours
86 hours

After 8 attempts (about 11 hours after the first) the delivery fails for good. Times are approximate: a retry can start up to about a minute later than the table says.

Your endpoint's answerWhat happens
2xxDelivered. No more attempts.
No answer: connection or TLS error, or no answer within 10 secondsRetried
408, 429 or any 5xxRetried
Any 3xxFails for good at once. Redirects are never followed.
Any other 4xx (for example 400, 401, 404)Fails for good at once

Retry-After. With a retried status, you can send a Retry-After header in seconds (for example Retry-After: 120) to wait longer before the next attempt. It can only make the wait longer than the table, never shorter, and at most 1 hour. A date value is ignored.

tip

To ask for a retry, answer 503, not 4xx. A 4xx other than 408 and 429 is never retried.

Pausing​

When 10 deliveries in a row fail for good, the endpoint is paused:

  • GET /webhooks/endpoints shows it with status: paused. consecutive_failures shows the current count.
  • Nothing is sent to it while it is paused, and its waiting retries are cancelled. Events that happen while it is paused are not kept.
  • Any delivered event (2xx) resets the count to 0. Most failures caused on the Mekari POS side, for example an event body that could not be built, do not count.

To resume, fix your receiver, check it with POST /webhooks/endpoints/{key}/test, then send the same PUT /webhooks/endpoints/{key} again. The endpoint becomes active, the count goes back to 0, and new events are sent from then on. test alone does not resume a paused endpoint. Then catch up on what you missed.

DELETE stops an endpoint on purpose and cancels its waiting deliveries. Setting it again later issues a new secret.

Order and Duplicates​

Delivery is at least once, and in no fixed order.

  • Duplicates happen. A network error after your endpoint saved an event can cause a retry. Save each event's id (also sent as X-Mekari-Event-ID) and skip an id you already processed. The id is the same on every retry.
  • Order is not guaranteed. A retry can arrive after a newer event, and sales made offline in the cashier app arrive late. Use occurred_at to order events about the same order or product, and for kitchen events also compare kitchen_status. When in doubt, read the current state with GET.

Catching Up After an Outage​

There is no API to send past events again. After your receiver was down, a delivery failed for good, or the endpoint was paused, read the current data from the API:

  • Orders: GET /orders for each outlet, with sold_at_from and sold_at_to covering the gap. Start a little before the gap, because sales made offline can carry an earlier time.
  • Returns, refunds and exchanges: GET /returns, GET /refunds and GET /exchanges for each outlet, newest first. The order_id filter works on all three lists, for example GET /returns?order_id=.
  • Products: GET /products.
  • Collections: GET /collections.

Then compare with what you have and update your records. Events that arrive later are still valid; drop the ones you already handled by id.