Webhooks
OverviewWebhooks allow your system to receive real-time event notifications from Atlar.
Use them to stay up to date with changes to payments, accounts, and other resources without polling the API.
Webhooks deliver HTTP POST requests to an HTTPS URL you configure whenever resources change.
Manage webhook configurations with the Platform API:
- Create webhook
- Create webhook signing key
- List webhooks
- Get webhook
- Update webhook (JSON Patch)
- Delete webhook
- List webhook signing keys
- Delete webhook signing key
Setting up a webhook
Unlike API v1 (where create returned a signing key in the same response), API v2 setup is two calls:
- Create webhook — configure the HTTPS URL, optional alias, and inclusive
filters(resource+eventTypes). - Create webhook signing key — create a signing key for that webhook id. The secret is returned once in this response; store it securely. Listing keys later never returns the secret again.
You need at least one signing key to validate the Webhook-Signature on incoming requests. You can hold one or two keys per webhook so key rotation can happen without downtime.
Example create webhook body:
{
"url": "https://example.com/my-atlar-webhooks",
"alias": "Payment updates",
"filters": [
{
"resource": "credit_transfers",
"eventTypes": ["CREATED", "UPDATED", "DELETED"]
},
{
"resource": "transactions",
"eventTypes": ["CREATED", "UPDATED"]
}
]
}Then create a signing key (empty body) against the new webhook id, for example:
POST /platform/v2beta/webhooks/{id}/keysThe 201 response includes id, created, and key (Base64). Keep key somewhere safe — subsequent List webhook signing keys responses omit it.
Event types vs event names
When you create or update a webhook, you subscribe using event types:
| Event type | Meaning |
|---|---|
CREATED | A new resource was created |
UPDATED | An existing resource changed |
DELETED | A resource was removed |
Filters are inclusive: you only receive events that match both the resource and one of the listed eventTypes.
Each delivered payload also includes event.name (for example FULLY_APPROVED on a credit transfer). That name is detail about what happened, not something you filter on when configuring the webhook. To stay in sync with Atlar for a resource, subscribe to all three event types for that resource.
AboutDELETEDevents
DELETEDis sometimes used for data cleanup rather than a normal business process.
For example, bookedtransactionsare not routinely deleted, but a rare cleanup (bank or Atlar side) may emitDELETED.
Resources you can subscribe to
Create webhooks with filters for these resources (API version 2 entity shapes):
| Resource | Typical use |
|---|---|
credit_transfers | Outgoing payments |
direct_debits | Incoming collections |
mandates | Direct debit mandates |
accounts | Bank accounts |
account_end_of_day_summaries | End-of-day account summaries |
transactions | Booked transactions |
pending_transactions | Pending / intraday transactions |
roles | IAM roles |
memberships | Organization memberships |
invitations | User invitations |
audit_log_entries | Audit log entries |
oauth_grants | OAuth grants |
Note: New webhooks should use these API v2 resource names. In particular, use
credit_transfers(not the legacypaymentsname), and do not create API v2 filters forexpected_transactions(that resource is not available for v2 webhooks).
Updating a webhook
Use Update webhook with JSON Patch (application/json-patch+json). You can replace /url, /filters, and /alias. Changing the URL sets verified to false again.
Webhooks that were created with the older event-name filter model cannot be updated via this endpoint. Recreate them with eventTypes filters instead.
Webhook payload
Each request body includes:
resource– which resource type changed (for examplecredit_transfers)apiVersion– major API version used to serializeentity(typically2)event– event metadata, includingtype(CREATED/UPDATED/DELETED),name,id,timestamp, andentityIdentity– a snapshot of the resource after the event
If two events happen close together, a later update may land before an earlier webhook is delivered. Always check entity.version (an incrementing integer) and ignore payloads with a lower version than the one you already stored.
Acting on webhooksAlways process the snapshot in
entity.
❗️Do not use onlyentity.idto make a separateGETfor the resource — read consistency can lag, and you might not see the version that corresponds to this event.
Example payload (credit transfer fully approved):
{
"resource": "credit_transfers",
"apiVersion": 2,
"event": {
"id": 3,
"type": "UPDATED",
"name": "FULLY_APPROVED",
"timestamp": "2022-05-04T18:47:32.213842599Z",
"originator": "ATLAR",
"message": "Automatically approved",
"organizationId": "0160f6ab-5741-49e1-af46-9138927e547e",
"entityId": "ec079994-619c-42e9-ac06-b50d4beea2e4"
},
"entity": {
"id": "76992987-48fc-4b03-b609-ea6fdc3045b4",
"organizationId": "0160f6ab-5741-49e1-af46-9138927e547e",
"amount": { "currency": "EUR", "value": 1502, "stringValue": "15.02" },
"date": "2022-05-07",
"scheme": "SCT",
"status": "APPROVED",
"version": 3,
"etag": "version:3"
}
}See also the Resource event reference for the full delivery schema.
Webhook retries
If your server responds with anything other than a 2xx HTTP status, Atlar retries the request.
Retries occur 3 times every 15 minutes for up to 12 hours.
If your system is unavailable longer than that, recover missed history from the resource /events endpoints (for example List credit transfer events).
Webhook security
Each webhook request includes:
Webhook-Signature(case-insensitive) – HMAC-SHA256 hex digest(s). Multiple signatures are comma-separated. Use this to verify authenticity and integrity.Webhook-Request-Timestamp(case-insensitive) – RFC 3339 UTC timestamp (nano precision). Use this to mitigate replay attacks.
Signature and timestamp verification
Create a signing key with Create webhook signing key (and again when you rotate). The secret is only returned once in that create response — store it securely.
Steps to validate:
- Decode the key from standard Base64 into bytes.
- Build the signing input: request body (raw JSON bytes) +
.+ timestamp header value. - Compute HMAC-SHA256 over that input.
- Encode the HMAC as a lowercase hex string.
- Compare to the header value with a constant-time comparison (the header may list multiple comma-separated signatures during key rotation — accept if any matches a key you trust).
- Reject requests whose timestamp is too old (for example older than 5 minutes).
See a full Go implementation (including max-age checks and multi-signature headers): signatureIsValid in atlar-webhook-examples. Additional examples (Java, JavaScript, Python) live in the same atlar-tech/atlar-webhook-examples repo — note the implementations differ slightly across languages.
Idempotency and ordering
- Idempotency: Treat deliveries as at-least-once. Use
event.id+entity.idas a unique key so duplicates are safe. - Ordering: Delivery is usually ordered but not guaranteed. Prefer
entity.version(orevent.timestamp) to determine the latest state.
Atlar will not send webhooks older than 120 hours, so you only need to retain processed event IDs for that window.
Key rotation
Rotate keys with Create webhook signing key, List webhook signing keys, and Delete webhook signing key. You can have one or two keys at a time so rotation can happen without downtime.
Going live
Before Atlar sends webhook calls to your URL, the configuration must be verified.
Contact [email protected] to complete verification.
Any change to the webhook url resets verified to false.
Updated 16 days ago
