Skip to main content
Webhooks send Payment, Refund, and Payout lifecycle events to your HTTPS endpoint. Use them to update orders and track refunds and payouts without continuous polling. Keep Payment retrieval available for reconciliation and for checking the latest state after a browser return.

Set up an endpoint

  1. In the Merchant Portal, select your merchant and the intended mode, then open Developers → Webhooks endpoints.
  2. Choose Add endpoint, enter a publicly reachable HTTPS URL, and select the event types your integration handles.
  3. Store the returned signing secret in your server-side secrets manager. It is shown when the endpoint is created; do not put it in frontend code, logs, screenshots, or support messages.
  4. Confirm that the endpoint is enabled. Create a Sandbox payment and verify that your server receives and acknowledges its subscribed events.
Use a direct HTTPS URL with a valid TLS certificate, for example https://shop.example.com/webhooks/flowlix. URLs cannot contain credentials, query parameters, or fragments, and must resolve to public addresses. Redirects are not followed. Your endpoint authenticates Flowlix using the signature below, not a browser session or an API key in the URL. Sandbox and Live destinations, events, and signing secrets are separate. Verify with the secret for the destination and mode receiving the request.

Event types

A Payout can move directly from PENDING to SUCCEEDED or FAILED, without a payout.processing event. Do not require every intermediate event or assume delivery order. Use Payout retrieval to reconcile its current state. Refund-related Payment events describe changes to refund totals; they do not add Payment statuses. A refunded Payment remains SUCCEEDED. Use amount_refunded, amount_refundable, and the individual Refund statuses. Safely acknowledge valid event types you do not handle, so compatible additions do not break your endpoint.

Event payload

Each delivery is an HTTPS POST with Content-Type: application/json and a Flowlix-Signature header. The envelope contains an immutable snapshot of the resource when the event occurred, not the latest state at delivery time.
request: null is normal for an automatic or provider-caused event; do not substitute the request that originally created the Payment or Payout. A Payout snapshot has no separate livemode field; use the envelope’s mode. For a Refund, use data.object.payment_id to retrieve its parent Payment.

Verify the signature

The header has the form t=<Unix seconds>,v1=<64 lowercase hexadecimal characters>. Its timestamp belongs to this delivery attempt, not to event.created_at.
  1. Read the raw request body as bytes, before parsing or reserializing JSON.
  2. Prefix those bytes with the header’s timestamp and a period: timestamp + "." + body.
  3. Compute HMAC-SHA256 using the signing secret’s UTF-8 bytes, including the whsec_ prefix. Do not base64-decode the secret or remove its prefix.
  4. Compare the expected and received signature with a constant-time comparison.
  5. Reject stale timestamps. The example below uses a recommended five-minute tolerance in either direction; keep your server clock synchronized.
Verify before trusting or parsing the event for business processing. JSON formatting, whitespace, or encoding changes alter the signature. Never log the signing secret or entire request body to debug a mismatch.

Acknowledge and process safely

Return a small, complete 2xx response promptly, after durably accepting the event. Do not perform slow business work before acknowledgement. A non-2xx response, a redirect, a connection failure, or a timeout is a failed attempt. Use a database uniqueness constraint on the Event id, scoped to your merchant integration if your storage serves multiple merchants. In one transaction, insert the event and a durable processing job. Commit before returning 2xx; if you cannot persist the event, return a non-2xx response. A duplicate already durably accepted can receive 2xx without a second job. The worker processes accepted events and retries its own failures. Protect external side effects, such as fulfilment, with their own idempotency key; receiving an event once does not make a business action exactly-once.

Automatic retries

Failed deliveries use the following scheduled offsets from creation of the delivery, including the initial attempt: Retries include positive jitter of up to 10% of the interval since the previous slot. These are scheduling offsets, not exact arrival guarantees. Missed retry slots can be skipped rather than replayed in a burst after downtime. Delivery stops after acknowledgement or exhaustion of the available retry slots. The same Event ID and snapshot can arrive more than once, with a fresh signature timestamp for a new attempt. Events can arrive out of order; do not overwrite a newer order state blindly with an older snapshot. Retrieve the current Payment when you need the latest state, and use its refunds array to reconcile Refunds. Keep a slower reconciliation loop for payments your system still considers pending. Webhook delivery and your business processing are separate: a 2xx response confirms receipt, not successful fulfilment.