Webhooks¶
Register a callback URL to receive push notifications when a scheduled export run finishes, instead of polling GET /export-runs/{scheduleId}/status.
GET /webhooks¶
Returns all registered webhooks for the authenticated tenant. The signing secret is never returned by this endpoint — it is only shown once, at creation time.
Status Codes¶
| Status | Description |
|---|---|
| 200 | Webhook list returned. |
| 401 | Missing or invalid API key. |
Example Request¶
curl https://ext.arc-aegis.billtrust.com/api/v1/remittance-export/webhooks \
-H "X-API-Key: <your-api-key>"
Example Response — 200¶
{
"data": [
{
"id": "3b6a9c00-1111-4abc-9def-000000000003",
"tenantId": "acme-corp",
"scheduleId": "8f2c1e40-1234-4abc-9def-000000000001",
"callbackUrl": "https://supplier.example.com/webhooks/arc",
"createdAt": "2026-06-01T10:00:00.000Z",
"updatedAt": "2026-06-01T10:00:00.000Z"
}
]
}
POST /webhooks¶
Registers a callback URL to receive export.completed and export.failed events. Scope it to a specific scheduleId, or omit scheduleId to receive events for all of your schedules.
The response includes a secret field shown only once — store it immediately, it cannot be retrieved again. Use it to verify the X-Webhook-Signature header on each delivery (see below).
Callback URLs are validated at registration time and rejected if they resolve to a private, loopback, or link-local address (SSRF protection).
Request Body¶
| Field | Type | Required | Description |
|---|---|---|---|
| scheduleId | string | No | Scope this webhook to a specific schedule. Omit to receive events for all schedules. |
| callbackUrl | string (uri) | Yes | HTTPS URL to receive delivery POST requests. Must not resolve to a private/loopback/link-local address. |
Status Codes¶
| Status | Description |
|---|---|
| 201 | Webhook registered. secret is included once in the response. |
| 400 | Validation error (e.g. missing callbackUrl, or callbackUrl fails the SSRF safety check). |
| 401 | Missing or invalid API key. |
Example Request¶
curl -X POST https://ext.arc-aegis.billtrust.com/api/v1/remittance-export/webhooks \
-H "X-API-Key: <your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"scheduleId": "8f2c1e40-1234-4abc-9def-000000000001",
"callbackUrl": "https://supplier.example.com/webhooks/arc"
}'
Example Response — 201¶
{
"id": "3b6a9c00-1111-4abc-9def-000000000003",
"tenantId": "acme-corp",
"scheduleId": "8f2c1e40-1234-4abc-9def-000000000001",
"callbackUrl": "https://supplier.example.com/webhooks/arc",
"secret": "9f8e7d6c5b4a...",
"createdAt": "2026-07-14T10:00:00.000Z",
"updatedAt": "2026-07-14T10:00:00.000Z"
}
GET /webhooks/{id}/deliveries¶
Returns the most recent delivery attempts (up to 100) for a registered webhook, newest first.
Path Parameters¶
| Parameter | Description |
|---|---|
id |
The webhook's ID. |
Status Codes¶
| Status | Description |
|---|---|
| 200 | Delivery attempt list returned. |
| 401 | Missing or invalid API key. |
| 404 | Webhook not found. |
Example Request¶
curl https://ext.arc-aegis.billtrust.com/api/v1/remittance-export/webhooks/3b6a9c00-1111-4abc-9def-000000000003/deliveries \
-H "X-API-Key: <your-api-key>"
Example Response — 200¶
{
"data": [
{
"webhookId": "3b6a9c00-1111-4abc-9def-000000000003",
"scheduleId": "8f2c1e40-1234-4abc-9def-000000000001",
"event": "export.completed",
"attempt": 1,
"status": "delivered",
"httpStatus": 200,
"error": null,
"createdAt": "2026-07-14T02:03:42.000Z"
}
]
}
DELETE /webhooks/{id}¶
Deletes a webhook. In-flight retries for previously triggered deliveries are not cancelled.
Path Parameters¶
| Parameter | Description |
|---|---|
id |
The webhook's ID. |
Status Codes¶
| Status | Description |
|---|---|
| 204 | Webhook deleted. |
| 401 | Missing or invalid API key. |
| 404 | Not found. |
Example Request¶
curl -X DELETE https://ext.arc-aegis.billtrust.com/api/v1/remittance-export/webhooks/3b6a9c00-1111-4abc-9def-000000000003 \
-H "X-API-Key: <your-api-key>"
Delivery mechanics¶
Each event delivery is a POST to your callbackUrl:
{
"event": "export.completed",
"scheduleId": "8f2c1e40-1234-4abc-9def-000000000001",
"payload": {
"runId": "1c9a2f10-5678-4bcd-8ef0-000000000002",
"scheduleId": "8f2c1e40-1234-4abc-9def-000000000001",
"status": "completed",
"startedAt": "2026-07-14T02:00:00.000Z",
"completedAt": "2026-07-14T02:03:41.000Z",
"rowCount": 18420,
"errorStage": null,
"errorDetail": null
},
"deliveredAt": "2026-07-14T02:03:42.000Z"
}
Supported event types: export.completed, export.failed.
Retrieving the run's data¶
On export.completed, use payload.runId to fetch the exact snapshot the webhook announced:
curl "https://ext.arc-aegis.billtrust.com/api/v1/remittance-export/export-runs/8f2c1e40-1234-4abc-9def-000000000001/data?runId=1c9a2f10-5678-4bcd-8ef0-000000000002" \
-H "X-API-Key: <your-api-key>"
Don't omit runId and call GET /export-runs/{scheduleId}/data without it — that returns the schedule's most recent completed run, which can silently be a newer run than the one this webhook announced if the schedule fires again before you fetch.
Verifying the signature¶
Every delivery includes:
X-Webhook-Signature: sha256=<hex>
This is an HMAC-SHA256 digest of the raw JSON request body, computed using your webhook's secret (from the POST /webhooks response). Recompute the digest on your end and compare it to the header value before trusting the payload.
Retries¶
Failed deliveries (non-2xx response, timeout, or connection error) are retried with exponential backoff:
| Attempt | Delay before this attempt |
|---|---|
| 1 | — (initial attempt) |
| 2 | 30s |
| 3 | 60s |
| 4 | 120s |
| 5 | 300s |
After 5 total attempts, delivery is abandoned. Each attempt (success or failure) is recorded and visible via GET /webhooks/{id}/deliveries. Each delivery request times out after 10 seconds if the callback URL does not respond.