Webhook API
sellerfox sends selected KPI data to your endpoint daily as JSON over HTTPS POST. This reference covers request headers, the payload schema, authentication, and delivery behavior.
For dashboard configuration, KPI selection, and management, see Webhooks.
HTTP request
This request shows a delivery with Bearer authentication to an example URL. Replace the host and path with your receiver.
POST /sellerfox/webhooks HTTP/1.1
Host: receiver.example.com
Content-Type: application/json
Authorization: Bearer <configured-token>
X-Webhook-ID: 65abc123def4567890123456
X-Webhook-Delivery-ID: 550e8400-e29b-41d4-a716-446655440000Prepare the HTTPS endpoint
The saved URL must be syntactically valid and publicly accessible. The URL must use https: and a domain name rather than an IPv4 or IPv6 address. sellerfox rejects local and internal addresses. Local testing requires a publicly accessible tunnel.
Request headers
| Field | Requirement | Type | Description |
|---|---|---|---|
| Content-Type | Always | string | Always application/json. |
| X-Webhook-ID | Always | string | ID of the saved webhook configuration; test-webhook is used when testing before saving. |
| X-Webhook-Delivery-ID | Always | string | New ID for each HTTP attempt. |
| Authorization | Conditional | string | Present only when Bearer Token or Basic Auth is configured for the webhook. |
Read the test status from the body field test. sellerfox creates a new X-Webhook-Delivery-ID for every HTTP attempt, retry, and test. Record the X-Webhook-Delivery-ID for troubleshooting, but do not use the header to identify retries of the same delivery.
Authenticate deliveries
| Mode | Credentials | What sellerfox sends |
|---|---|---|
| None | None | No Authorization header |
| Bearer Token | Token | Authorization: Bearer <configured-token> |
| Basic Auth | Username and password | Authorization: Basic <base64(username:configured-password)> |
Payload
All webhook types share the same JSON envelope. This example shows a marketplace webhook:
{
"webhookId": "65abc123def4567890123456",
"webhookType": "marketplace-webhook",
"timestamp": "2026-08-13T00:00:10.000Z",
"test": false,
"data": [
{
"date": "2026-08-12",
"Sales (Total)": 1234.56,
"Units": 42
}
],
"metadata": {
"workspaceId": "65abc123def4567890123457",
"workspaceName": "Example workspace",
"from": "2026-07-13T00:00:00.000Z",
"to": "2026-08-12T23:59:59.999Z",
"kpis": ["Sales (Total)", "Units"],
"marketplaceDomain": "amazon.de"
}
}Shared fields
| Field | Requirement | Type | Description |
|---|---|---|---|
| webhookId | Always | string | Saved webhook configuration ID, or test-webhook for a pre-save test request. |
| webhookType | Always | string | Identifier for the selected webhook type. |
| timestamp | Always | string | Time when the payload for this attempt was created. |
| test | Always | boolean | Whether this is a dashboard test request. |
| data | Always | array | Selected KPI rows; the array can be empty. |
| metadata | Always | object | Workspace, window, KPI, and scope metadata. |
| Field | Requirement | Type | Description |
|---|---|---|---|
| workspaceId | Always | string | Workspace ID. |
| workspaceName | Always | string | Current workspace name. |
| from | Always | string | Inclusive window start. |
| to | Always | string | Inclusive window end. |
| kpis | Always | array | English labels used as KPI keys in data, in the configured order. |
The envelope timestamp records when the payload for the current attempt was created. The timestamp is not a row date and may change on retry. data is always an array and may be empty. metadata.from and metadata.to define the query window, including both boundaries. Type-specific metadata that does not apply is omitted rather than set to null.
Data rows and missing values
Marketplace and product rows use date-only values. A KPI with no value is omitted from the row rather than sent as null. Keyword rows use full ISO timestamps in date and may include null for a KPI. Your receiver must accept both shapes.
When metadata.marketplaceDomain is present, all rows in data refer to the marketplace it identifies, such as amazon.de.
KPI keys and units
metadata.kpis lists the selected KPIs in the configured order. The KPI labels in metadata.kpis and the KPI keys in data are always in English, regardless of the dashboard language.
The payload does not include units or currency information, including the workspace target currency. It also does not include a schema describing the data types of the KPI values.
Handle schema changes
Handle changes to the payload
The payload has no version field. Accept unknown fields and set aside payloads with an unknown type identifier for review.
Webhook types
Each type has its own type identifier, data scope, and scope metadata. Select the webhookType value to inspect its example payload and additional metadata. You can choose between one and 20 KPIs for each webhook. The workspace allowance determines how many webhooks you can create. To send the same data to several endpoints, create multiple webhooks with identical settings and different URLs.
Marketplacemarketplace-webhook
Delivers data for a single marketplace once a day.
- KPI limit
- 20
- Available
- 136
Selected type: Marketplace (marketplace-webhook)
{
"webhookId": "65abc123def4567890123456",
"webhookType": "marketplace-webhook",
"timestamp": "2026-08-13T00:00:10.000Z",
"test": false,
"data": [
{
"date": "2026-08-12",
"Sales (Total)": 1234.56,
"Units": 42
}
],
"metadata": {
"workspaceId": "65abc123def4567890123457",
"workspaceName": "Example workspace",
"from": "2026-07-13T00:00:00.000Z",
"to": "2026-08-12T23:59:59.999Z",
"kpis": [
"Sales (Total)",
"Units"
],
"marketplaceDomain": "amazon.de"
}
}Response and limits
sellerfox follows up to five redirects and evaluates only the final response. Only status codes from 200 through 299 indicate success. Any other status, too many redirects, a network or TLS error, or a timeout causes the attempt to fail.
Acknowledge a delivery
Verify the configured credentials before accepting a request. Store the request durably or add the request to a durable queue. Confirm successful storage with 2xx, preferably 204. Respond within 30 seconds for scheduled deliveries and 10 seconds for tests. Run processing that could exceed the response timeout after acknowledgment. This avoids processing-related timeouts and additional delivery attempts for scheduled webhooks. Never acknowledge a delivery that exists only in memory: you cannot request the delivery again after acknowledgment.
Scheduled and test deliveries compared
| Property | Scheduled request | Test request |
|---|---|---|
| test | false | true |
| Data | Current data retrieved for this delivery | Current data retrieved for this delivery, not generated sample data |
| Date window | Inclusive 31-day window ending yesterday | The same window |
| Timeout | 30 seconds | 10 seconds |
| Request-body limit | 10 MiB | 1 MiB |
| Response-body limit | 10 MiB | 5 MiB |
| Delivery history | Created and updated | Not created |
| Retries | Up to three total attempts | None |
| Success/failure counters | Updated | Unchanged |
Exceeding the applicable timeout or either body-size limit causes the attempt to fail.
Delivery and retries
sellerfox starts scheduled deliveries daily and checks hourly whether another delivery attempt is due. Wait a few hours before treating a delivery as lost, and do not depend on an exact arrival time. A scheduled delivery includes at most three attempts: the initial attempt and up to two retries.
For each retry, sellerfox fetches the current data again, rebuilds the payload, and creates a new envelope timestamp and a new X-Webhook-Delivery-ID. The original date range remains unchanged. Each failed HTTP attempt increases the consecutive-failure count; a successful attempt resets the failure count. After ten consecutive failed attempts, sellerfox disables the webhook. Resolve the cause and follow Webhooks → Monitor deliveries to restore webhook delivery.
Webhook and delivery IDs
Webhook ID: webhookId in the body and X-Webhook-ID in the header identify the webhook. Both fields contain the same value, which stays the same across retries.
Delivery attempt ID: X-Webhook-Delivery-ID identifies a single request and changes with each retry. Log this ID to trace individual attempts.
Delivery ID in the dashboard: The ID under “View History” identifies the entire delivery and stays the same across retries. It is not sent in the request and cannot be matched to X-Webhook-Delivery-ID.
Implement a receiver
These examples show HTTP receipt and acknowledgment after queuing the request. durableQueue and durable_queue represent your own durable queue. Add validation of the configured credentials and connect the queue before use.
import express from 'express'
const app = express()
app.use(express.json({ limit: '10mb' }))
app.post('/sellerfox/webhooks', async (request, response) => {
await durableQueue.add({ headers: request.headers, payload: request.body })
response.sendStatus(204)
})Safe upserts
The window covers 31 dates through yesterday, inclusive, and overlaps the previous day's window by 30 dates. Previously delivered values may change. sellerfox creates one delivery per webhook and date window, so replace saved rows for the same scope and date instead of only appending new rows.
Use this processing model for retries that contain freshly queried data and for overlapping scheduled windows across all webhook types:
Receive the request
- Verify credentials
If configured, verify the Bearer token or Basic credentials.
- Validate the payload
Parse JSON and require data to be an array.
- Add to a durable queue
Store {headers, payload} under a receiver-generated record ID.
Respond to sellerfox
After durable storage and before the sender timeout.
Process separately from the queue
- Log the delivery attempt
Record X-Webhook-Delivery-ID for observability, never for retry deduplication.
- Determine the scope
Build scope from payload.webhookId, payload.webhookType, and the applicable metadata fields.
- Group by date
Group payload.data by row.date.
- Replace rows for each group
For each {scope, date}, replace stored rows with the received rows.
Show pseudocode
receive(request):
verify the configured Bearer or Basic credential, when one is configured
parse JSON and require data to be an array
durably enqueue {headers, payload} under a receiver-generated record ID
return 204 before the sender timeout
process(headers, payload):
record X-Webhook-Delivery-ID for observability, never as a retry deduplication key
scope = {payload.webhookId, payload.webhookType, applicable metadata scope fields}
groups = group payload.data by row.date
for each {date, rows} in groups:
replace the receiver's rows for {scope, date} with rowsFor each date received, replace the previously stored rows with the new rows. Only replace rows with matching webhookId, webhookType, and metadata that identifies the data scope. For marketplace-scoped webhooks, this includes metadata.marketplaceDomain so data from different marketplaces stays separate.
This applies corrections and prevents duplicate entries when multiple deliveries contain the same date. It works for every webhook type.
Log and monitor deliveries
Keep the requests you receive and log whether your endpoint accepted each request successfully or encountered an error. This lets you trace which data arrived and where problems occurred. Respond to repeated errors early: sellerfox disables the webhook after ten failed delivery attempts in a row.
The dashboard has these limits:
- Responses from your endpoint: Test results and history entries for successful scheduled deliveries show at most the first 5,000 characters of the response body.
- Successful deliveries: sellerfox deletes the history entry 30 days after delivery.
- Pending and failed deliveries: These history entries are not automatically deleted after 30 days.
Test the integration
Create the webhook as described in Create and test a webhook.
Test the receiver
Run a test from the dashboard with “Test Connection”. The test uses current data, not generated fixtures. A data-fetch failure can also produce a valid request with data: [].
When you test a webhook before saving it, both webhookId and X-Webhook-ID contain test-webhook. Tests of a saved webhook use its ID.
If the receiver returns an error, sellerfox displays a structured test result. Errors during preparation or sending may instead produce a general error message without further details.
Send a request with cURL
Save an example payload as payload.json and replace the URL and token with your receiver's values. This checks processing at your endpoint; the dashboard test above also checks delivery from sellerfox.
curl -i -X POST https://receiver.example.com/sellerfox/webhooks \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <configured-token>' \
--data-binary @payload.jsonRelated
- Webhooks — configure, test, and monitor a delivery in the dashboard.
- Troubleshooting — diagnose a failing test or a stopped delivery.
- KPI Explorer — look up KPI definitions and units.
- Data refresh schedule — see when the data behind a delivery changes.