Browse the docs
Webhooks
Subscribe to Flxpoint webhook events, handle what each event sends, read the delivery log, retry failed events, and keep polling as the fallback.
Use this when you want Flxpoint to notify your system when a fulfillment request starts processing or an order is imported, instead of only asking the API on a schedule.
A webhook is a configuration on your account: a URL, the events it subscribes to, and an optional email for failure notifications. Flxpoint posts each subscribed event to that URL, records every delivery in an event log, and lets you retry events from the API. This guide covers the whole loop, and why polling stays your safety net.
- Two events exist today:
FulfillmentRequestProcessingEventandOrderImportedEvent. - The configuration endpoints are spelled
/webhhok/configurations(double h). Use the paths exactly as shown. - Every delivery is logged.
GET /webhook/configurations/{id}/event-logsshows its status, attempts and next try;POST /webhook/event/retrysends failed events again. - Treat an event as a hint and re-read the record with your token. Keep a poll running; the fulfillment request event does not fire for every fulfillment request.
| Event | When it is generated | What data carries |
|---|---|---|
FulfillmentRequestProcessingEvent | When a fulfillment request moves into Processing, including a new fulfillment request created directly in Processing. | The fulfillment request, read the same way GET /fulfillment-requests/{fulfillmentRequestId} returns it. |
OrderImportedEvent | Named for orders imported into Flxpoint. The reference documents its payload but not its exact trigger, so confirm it against a test order before you rely on it. | The order, described by the OrderImportedEvent schema: order fields, addresses, line items, fulfillment requests and the order's status fields. |
Every delivery uses the same envelope, the WebhookEvent model:
| Field | Type | Meaning |
|---|---|---|
id | string | Unique identifier for the event. Use it as your dedupe key. |
eventType | string | FulfillmentRequestProcessingEvent or OrderImportedEvent. |
createdAt | integer (int64) | Timestamp of when the event was created. |
isTestEvent | boolean | Distinguishes a test event from a production event. |
data | object | The payload for the event type, as in the table above. |
Fulfillment requests that skip Processing never send this event. When a source is set up to receive fulfillment requests through the Vendor Portal, Flxpoint moves its fulfillment requests straight to Processed, so FulfillmentRequestProcessingEvent is never generated for them. If Flxpoint cannot read the fulfillment request at the moment the event is generated, the event is skipped silently: no error is returned anywhere and the event is not retried.Send the URL and the events. webhookUrl and subscribedEvents are required; configurationName, notificationEmail, sourceId and channelId are optional. Use an Account token: the reference states it for listing and updating configurations.
curl -X POST "https://api.flxpoint.com/webhhok/configurations" \
-H "X-API-TOKEN: YOUR_ACCOUNT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"configurationName": "FR processing to ERP",
"webhookUrl": "https://example.com/flxpoint/webhooks",
"notificationEmail": "integrations@example.com",
"subscribedEvents": ["FulfillmentRequestProcessingEvent"]
}'A 200 returns the WebhookConfiguration: its id (keep it, every later call needs it), configurationName, webhookUrl, notificationEmail, sourceId, channelId, status, subscribedEvents, createdAt and updatedAt. A malformed body returns 400; a missing or wrong token returns 401.
Choose the name, source and channel carefully. The update request has noconfigurationName,sourceIdorchannelId, so they cannot be changed after creation. To change them, create a new configuration and delete the old one.
notificationEmail is where Flxpoint sends webhook failure notifications. The same configurations appear in the Flxpoint app under account settings, Webhooks.
Flxpoint posts each event to your webhookUrl. Its delivery timeout and the exact response it counts as delivered are not documented, so keep the request short: store the event, respond, and do the real work afterwards.
// Pseudo-code. Adapt to your stack.
app.post("/flxpoint/webhooks", async (req, res) => {
const event = req.body; // WebhookEvent envelope
const isNew = await db.insertIfAbsent("flx_events", event.id); // dedupe on event.id
if (isNew) await queue.push(event); // the slow work happens in a worker
res.status(200).end();
});
// Worker: re-read the record with your own token before acting on it.
async function handleEvent(event) {
if (event.eventType === "FulfillmentRequestProcessingEvent") {
const fr = await flxGet(`/fulfillment-requests/${event.data.id}`);
await processFulfillmentRequest(fr);
}
}Verifying an event
The API reference does not document a signature header for webhook deliveries. Treat the body as a notification rather than proof: take the record id from data, read the record back with your X-API-TOKEN, and act on what the API returns. A forged or stale event then cannot change anything on your side, and you always work from the current state.
Duplicates
Make the handler safe to run twice for the same id. You can send an event again with the retry endpoint, and your own queue may replay it after a crash; a unique constraint on the event id turns the second insert into a no-op.
Every event sent through a configuration is logged against it. Page through the log, optionally filtered by delivery status:
curl -G "https://api.flxpoint.com/webhook/configurations/42/event-logs" \
-H "X-API-TOKEN: YOUR_ACCOUNT_TOKEN" \
--data-urlencode "webhookDeliveryStatus=external_failure" \
--data-urlencode "page=1" \
--data-urlencode "pageSize=100"page defaults to 1; pageSize defaults to 50 and allows up to 100. The response is an array of WebhookLog entries: id, status, eventType, eventKey, createdAt, lastTriedAt, nextTryAt, publishedAt, retryCount, manualRetryCount, statusCode and statusMessage. An unknown configuration id returns 404.
status | What it means |
|---|---|
processing | Not delivered yet. nextTryAt shows when the next attempt is due. |
published | Delivered. publishedAt is the time of the successful delivery. |
internal_failure | Delivery failed. The reference does not define the split between the two failure states; read statusCode and statusMessage on the entry. |
external_failure | Delivery failed. As above. |
Flxpoint retries on its own schedule: lastTriedAt is the most recent attempt, nextTryAt the next one, and retryCount and manualRetryCount count the automatic and manual attempts. The number of automatic attempts and the gap between them are not documented, so read nextTryAt rather than assuming a schedule.
Once your endpoint is healthy again, send the failed events back. Both fields are required; pass the id values from the event log and isAutomatedRetry: false for a retry you trigger yourself.
curl -X POST "https://api.flxpoint.com/webhook/event/retry" \
-H "X-API-TOKEN: YOUR_ACCOUNT_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "eventIds": [90211, 90214], "isAutomatedRetry": false }'The call returns 202 Accepted: the retry is queued, not finished. Check the event log again for the new status. A malformed body returns 400.
An update always carries webhookUrl and subscribedEvents (both required), plus notificationEmail and status if you are changing them. status takes active, disabled or deleted.
curl -X PATCH "https://api.flxpoint.com/webhhok/configurations/42" \
-H "X-API-TOKEN: YOUR_ACCOUNT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"webhookUrl": "https://example.com/flxpoint/webhooks",
"subscribedEvents": ["FulfillmentRequestProcessingEvent"],
"status": "disabled"
}'There is no DELETE endpoint: deleting a configuration is this same update with "status": "deleted", which is how the Flxpoint app does it. The app warns that deleting cannot be undone and that the configuration's event log is deleted with it, so export anything you need from the log first. Read a configuration back with GET /webhhok/configurations/{id}, or list them all with GET /webhhok/configurations.
Run a poll alongside the webhook and use the event to react sooner, not as your only trigger. Polling catches what the event never reports (fulfillment requests that go straight to Processed, an event skipped at generation) and anything your endpoint missed while it was down.
# Fulfillment requests in Processing for one source
curl -G "https://api.flxpoint.com/fulfillment-requests" \
-H "X-API-TOKEN: YOUR_TOKEN" \
--data-urlencode "filterStatus=Processing" \
--data-urlencode "filterSourceId=1234" \
--data-urlencode "filterPageSize=100"
# Orders changed since your last run, including their fulfillment requests and shipments
curl -G "https://api.flxpoint.com/orders" \
-H "X-API-TOKEN: YOUR_TOKEN" \
--data-urlencode "orderModifiedAfter=2026-10-01T00:00:00Z"orderModifiedAfter matches orders where the order or any of its sub-components changed (line items, addresses, fulfillment requests, shipments, source invoices, returns and RMAs). updatedAfter covers changes to the order itself only. Keep each token under 2 requests per second. Polling fulfillment requests covers cadence and dedupe in detail.
- Create Webhook Configuration (
POST /webhhok/configurations) - List Webhook Configurations for an account (
GET /webhhok/configurations) - Get Webhook (
GET /webhhok/configurations/{id}) - Update Webhook Configuration (
PATCH /webhhok/configurations/{id}) - Get Webhook Configuration Event Logs (
GET /webhook/configurations/{id}/event-logs) - Retry Webhook Event (
POST /webhook/event/retry) - Get Fulfillment Request (
GET /fulfillment-requests/{fulfillmentRequestId}) - Get Fulfillment Requests (
GET /fulfillment-requests) - Get Orders (
GET /orders) - Polling fulfillment requests and Authentication & rate limits