Skip to content

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.

http
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-446655440000

Prepare 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

Request headers
FieldRequirementTypeDescription
Content-TypeAlwaysstringAlways application/json.
X-Webhook-IDAlwaysstringID of the saved webhook configuration; test-webhook is used when testing before saving.
X-Webhook-Delivery-IDAlwaysstringNew ID for each HTTP attempt.
AuthorizationConditionalstringPresent 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

Authentication modes
ModeCredentialsWhat sellerfox sends
NoneNoneNo Authorization header
Bearer TokenTokenAuthorization: Bearer <configured-token>
Basic AuthUsername and passwordAuthorization: Basic <base64(username:configured-password)>

Payload

All webhook types share the same JSON envelope. This example shows a marketplace webhook:

json
{
  "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

Envelope fields
FieldRequirementTypeDescription
webhookIdAlwaysstringSaved webhook configuration ID, or test-webhook for a pre-save test request.
webhookTypeAlwaysstringIdentifier for the selected webhook type.
timestampAlwaysstringTime when the payload for this attempt was created.
testAlwaysbooleanWhether this is a dashboard test request.
dataAlwaysarraySelected KPI rows; the array can be empty.
metadataAlwaysobjectWorkspace, window, KPI, and scope metadata.
Shared metadata fields
FieldRequirementTypeDescription
workspaceIdAlwaysstringWorkspace ID.
workspaceNameAlwaysstringCurrent workspace name.
fromAlwaysstringInclusive window start.
toAlwaysstringInclusive window end.
kpisAlwaysarrayEnglish 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)

json
{
  "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

Scheduled and test delivery matrix
PropertyScheduled requestTest request
testfalsetrue
DataCurrent data retrieved for this deliveryCurrent data retrieved for this delivery, not generated sample data
Date windowInclusive 31-day window ending yesterdayThe same window
Timeout30 seconds10 seconds
Request-body limit10 MiB1 MiB
Response-body limit10 MiB5 MiB
Delivery historyCreated and updatedNot created
RetriesUp to three total attemptsNone
Success/failure countersUpdatedUnchanged

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.

js
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

  1. Verify credentials

    If configured, verify the Bearer token or Basic credentials.

  2. Validate the payload

    Parse JSON and require data to be an array.

  3. Add to a durable queue

    Store {headers, payload} under a receiver-generated record ID.

Respond to sellerfox

Return 204

After durable storage and before the sender timeout.

Process separately from the queue

  1. Log the delivery attempt

    Record X-Webhook-Delivery-ID for observability, never for retry deduplication.

  2. Determine the scope

    Build scope from payload.webhookId, payload.webhookType, and the applicable metadata fields.

  3. Group by date

    Group payload.data by row.date.

  4. Replace rows for each group

    For each {scope, date}, replace stored rows with the received rows.

The response confirms durable storage. Further processing happens separately.
Show pseudocode
text
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 rows

For 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.

bash
curl -i -X POST https://receiver.example.com/sellerfox/webhooks \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <configured-token>' \
  --data-binary @payload.json