Webhooks
Overview
Webhooks 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
Webhooks allow you to receive HTTP POST requests with payloads whenever certain events occur.
You can use the Webhook endpoints to add or modify webhook configurations for your organization.
The endpoints allow you to specify the HTTPS URL where you want to receive webhook requests.
Events
Webhook payloads contain the new state of the resource after the event occurred.
There are three types of events: CREATED
, UPDATED
, and DELETED
.
If you want to maintain a complete copy of the data that Atlar holds, you need to listen to all three event types for a given resource and update your system accordingly.
Note: When creating a webhook, you can provide an inclusive
filter
to specify which event types you want to receive.
AboutDELETED
events
The event typeDELETED
may sometimes be used for data cleanup.
For example, for thetransactions
resource there is no regular business process that would remove booked entries.
However, in rare cases (e.g., an issue at the Bank or Atlar), cleanup may require aDELETED
event.
Webhook Payload
Each webhook payload contains:
- Metadata about the affected resource and the API version (
resource
,apiVersion
). - Entity – the resource as it existed after the event (
entity
).- This may not always reflect the absolute latest state if multiple updates occur in rapid succession.
- If two events happen close together, the second event might update the resource before the first webhook arrives.
- Always check
entity.version
(an incrementing integer) and ignore payloads with a lower version than the one you have stored.
- Event information (
event
andresource
).
Acting on webhooks
Always process the snapshot of the resource provided in theentity
property.
❗️Do not use onlyentity.id
to make a separateGET
request to fetch the resource, because read consistency may delay updates and you might not receive the version corresponding to the webhook event.
Webhook Retries
If your server responds with anything other than a 2xx
HTTP status, Atlar will retry the request.
Retries occur 3 times every 15 minutes for up to 12 hours.
If your system is unavailable longer than 12 hours, you can retrieve missed events using the Events API.
Webhook Security
Each webhook request includes HTTP headers to ensure authenticity and integrity:
- Signature
- Header:
Webhook-Signature
(case-insensitive) - Format: HMAC-SHA256
- Example:
e71354d023f850abcb1bfd884de2874bc973dcbb4b44acac5fe4ca89e28d12ed
- Multiple signatures are separated by a comma
,
. - Purpose: Verify that the webhook was sent by Atlar and has not been altered.
- Header:
- Timestamp
- Header:
Webhook-Request-Timestamp
(case-insensitive) - Format: RFC 3339 (UTC, nano precision)
- Example:
2022-10-11T10:13:14.000000015Z
- Purpose: Mitigates replay attacks by validating the age of the request.
- Header:
Signature & Timestamp Verification
Each webhook endpoint has a unique webhook key, generated when the endpoint is created.
You can find this key once after creation in the Webhook API.
Store the key securely—use it to verify the Webhook-Signature
.
Steps to validate:
- Decode the key into bytes (standard Base64).
- Create a signature payload by concatenating:
- The webhook request body as a JSON string.
- A period
.
. - The timestamp from the header.
- Compute an HMAC using SHA256.
- Encode the HMAC bytes into a hexadecimal string.
- Compare the computed signature to the header value using constant-time comparison (to avoid timing attacks).
- Check the difference between the request timestamp and the current time to ensure the message is not too old (e.g., tolerance of 5 minutes).
If multiple keys exist during key rotation, multiple signatures will be provided in the header (comma-separated).
Code example (Go)
func signatureIsValid(sigHeader, tsHeader, payload, base64Key string) (bool, error) {
key, err := base64.StdEncoding.DecodeString(base64Key)
if err != nil {
return false, fmt.Errorf("failed to decode key, %w", err)
}
sig, err := hex.DecodeString(sigHeader)
if err != nil {
return false, nil
}
mac := hmac.New(sha256.New, key)
mac.Write([]byte(payload + "." + tsHeader))
return hmac.Equal(mac.Sum(nil), sig), nil
}
(More examples in various languages (Go, Java, JavaScript, Python) are available at https://github.com/atlar-tech/atlar-webhook-examples)
Example values
Webhook-Signature: fe8f799f90ecfe57ce9ae19d3429be0ca3c0e5ae336fdf3e08dd1f7b60a15a6f
Webhook-Request-Timestamp: 2022-10-06T07:26:57.237369365Z
Key (base64): agj+xWKk3gqkP+SsCsljkjbDth7bxguqVMRd4K3wm1I=
Body: {"resource":"payments","event":{"organizationId":"1f91e001-9295-46b6-9438-ef6f0fed18fc","entityId":"422a164c-4548-11ed-8d31-0a58a9feac02","id":0,"timestamp":"2022-10-06T07:26:56.837022728Z","name":"CREATED","originator":"90b51164-d782-4238-a0bf-c1ff66a8a83e","message":"","details":{"request":"ewogICAgImFtb3VudCI6IHsKICAgICAgICAiY3VycmVuY3kiOiAiU0VLIiwKICAgICAgICAidmFsdWUiOiA1MDAwCiAgICB9LAogICAgInNvdXJjZUFjY291bnRJZCI6ICJjZjAxMGY5MC04M2UyLTQyMGQtYjE2ZS1lYjY4ZGJmZDcwNDciLAogICAgImRlc3RpbmF0aW9uRXh0ZXJuYWxBY2NvdW50SWQiOiAiZTgwZGU1ZTAtMWIwNS00OTc0LThjNzMtMDg0MDI3MTg1YzdmIiwKICAgICJkYXRlIjogIjIwMjItMTAtMTAiLAogICAgInJlbWl0dGFuY2VJbmZvcm1hdGlvbiI6IHsKICAgICAgICAidHlwZSI6ICJVTlNUUlVDVFVSRUQiLAogICAgICAgICJ2YWx1ZSI6ICJUZXN0aW5nIHdlYmhvb2tzIgogICAgfSwKICAgICJwYXltZW50U2NoZW1lVHlwZSI6ICJTQ1QiCn0="}},"entity":{"amount":{"currency":"SEK","value":5000},"approvalChain":{"approvalSteps":[{"id":"b698ab4e-efec-4c97-9133-88904022cd1b","requiredRole":{"id":"4ce82d1a-0ebf-46e7-96ba-7664cd48e4af","name":"Owner","owner":true},"status":"PENDING","updated":"0001-01-01T00:00:00Z"}],"triggeredApprovalChainId":"54e2c37d-fa95-4d5b-bbcf-b99c8ff8676f"},"attachedTransactions":[],"created":"2022-10-06T07:26:56.836974Z","date":"2022-10-10","destinationCounterparty":{"id":"7af0ea0b-7366-42aa-ad83-49e93e41ce5d","identifiers":[],"name":"Company Inc.","partyType":""},"destinationExternalAccount":{"bank":{"bic":"12345678900","id":"","name":""},"counterpartyId":"7af0ea0b-7366-42aa-ad83-49e93e41ce5d","id":"e80de5e0-1b05-4974-8c73-084027185c7f","identifiers":[{"holderName":"Test","market":"DE","number":"DE66500105172794778236","type":"IBAN"}],"organizationId":"1f91e001-9295-46b6-9438-ef6f0fed18fc"},"externalMetadata":null,"id":"422a164c-4548-11ed-8d31-0a58a9feac02","organizationId":"1f91e001-9295-46b6-9438-ef6f0fed18fc","paymentScheme":{"displayName":"Sepa Credit Transfer","type":"SCT"},"paymentSchemeType":"SCT","reconciliation":{"status":""},"remittanceInformation":{"type":"UNSTRUCTURED","value":"Testing webhooks"},"sourceAccount":{"affiliation":{"id":"49b72264-fae5-4720-89cf-f0d6fd5f727e","name":"My bank"},"bank":{"bic":"ATLRSESSXXX","id":"3dde93bf-49d1-44e4-a288-4bf0d4e31574","name":"Testbank"},"id":"cf010f90-83e2-420d-b16e-eb68dbfd7047","identifiers":[{"holderName":"Test Testsson","market":"DE","number":"DE77500105179251553356","type":"IBAN"}],"name":"My EUR account","owner":{"name":""}},"status":"CREATED"}}
Idempotency & Event Ordering
- Idempotency: Your webhook handler must handle duplicate events gracefully.
Use the combination ofevent.id
andentity.id
as a unique key to ensure that multiple identical webhook calls produce the same result. - Ordering: Webhooks are typically delivered in order, but this is not guaranteed.
To determine the latest state, rely onentity.version
orevent.timestamp
.
Atlar will never send webhooks older than 120 hours, so you only need to store processed event IDs for that time.
Key Rotation
Webhook keys can be rotated anytime using the /v1/webhooks/{id}/keys
endpoints.
You can have one or two keys simultaneously to allow seamless rotation without downtime.
Going Live
Before Atlar starts sending webhook calls to your endpoint, the webhook configuration must be verified.
Contact [email protected] to complete verification.
Any modification to the webhook url
will reset verified
to false
.
Updated about 6 hours ago