Skip to navigation

Webhooks

The Webhooks API allows you to receive realtime events about changes in other API resources. It eliminates the need for polling, reducing unnecessary API calls and resource utilization, allowing you to remain under the rate limits.

Create a webhook

To create a webhook, you can use the API or the SDK as your preferred method. A webhook requires a url and a set of events to receive notifications on. There’s a limit of 10 webhooks per organization.

POST
/v3/webhooks
curl -X "POST" \
"https://api.ntropy.com/v3/webhooks" \
-H "Accept: application/json" \
-H "X-API-KEY: cd1H...Wmhl" \
-H "Content-Type: application/json" \
-d '{
"hmac_secret": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"url": "https://example.com:5689/",
"events": [
"batches.completed",
"batches.error"
],
"token": "hunter2"
}'
Response
{
"url": "https://example.com:5689/",
"events": [
"batches.completed",
"batches.error"
],
"id": "e94a150d-40af-4e96-8aa7-2948a6b4d8d3",
"created_at": "2024-10-03T02:53:30.167953",
"enabled": true,
"token": "hunter2"
}

Webhook handling

When an event occurs, Ntropy will make a POST request to the url of the webhook. If you specified a token when creating the webhook, this string will be included in the X-Ntropy-Token header.

Signature verification

Each webhook can have its own optional 32-byte secret, supplied as exactly 64 hexadecimal characters in the hmac_secret field. You can generate one with secrets.token_hex(32) in Python. The secret is never returned in API responses. Rotate it by sending a new hmac_secret to PATCH /v3/webhooks/{id}, or set hmac_secret to null to disable signing.

Requests include X-Ntropy-Signature: t=<unix seconds>,sha256=<hex digest>. The digest is HMAC-SHA256 of the timestamp as ASCII, a literal . separator, and the exact raw request-body bytes, using the hex-decoded secret. Verify it before parsing or processing the body; reserializing JSON can change the signature. Check the authenticated timestamp against your clock to reject stale deliveries (for example, with a five-minute tolerance).

import hmac
import time
fields = dict(part.split("=", 1) for part in signature_header.split(","))
timestamp = fields["t"]
signed_body = timestamp.encode("ascii") + b"." + raw_body
expected = hmac.digest(bytes.fromhex(hmac_secret), signed_body, "sha256").hex()
if not hmac.compare_digest(expected, fields["sha256"]):
raise ValueError("Invalid webhook signature")
if abs(time.time() - int(timestamp)) > 300:
raise ValueError("Webhook timestamp outside tolerance")

Each delivery attempt, including retries, gets a fresh timestamp and is signed with the webhook’s current secret. Webhooks without an hmac_secret are unsigned.

The webhook call has a timeout limit of 10 seconds, so any busy processing of the event should be deferred. Responses with 2xx as status code are considered as successful.

The body of the POST request will have the following schema.

{
"event_id": "bab90a5e-1321-...", # unique identifier
"event_type": "batches.completed", # the event that occurred
"data": {}, # the event payload
}

The data field of the webhook request will follow the same schema as the resource the event corresponds to. For example, in a batches.finished event, the data field will contain a Batch object, the same schema as the /v3/batches/{id} endpoint.

Retry policy

If a non-2xx response is received, a timeout of 10 seconds is exceeded, or the request fails, the request will be retried with the same event_id for up to 24 hours. Occasionally the webhook might be called multiple times even after a successful response is received. We recommend that you log the list of already processed event_id to not handle an event twice.

Re-enabling webhooks

Webhooks have a limit of non-2xx consecutive responses that they can receive before being disabled. You may re-enable a webhook by setting the enabled attribute to True.

from ntropy_sdk import SDK
sdk = SDK("cd1H...Wmhl" )
sdk.webhooks.patch(id="e94a150d-40af-4e96-8aa7-2948a6b4d8d3", enabled=True)

Events

In the previous example we created a webhook that will get notified on completion or failed runs of batches and bank statements. The available list of events is below:

Event TypeDescription
bank_statements.completedBank statement has finished processing
bank_statements.errorBank statement encountered an error processing
batches.completedBatch has finished processing
batches.errorBatch encountered an error processing
reports.resolvedReport has been resolved
reports.rejectedReport was rejected, check rejection_reason
reports.pendingReport is being investigated