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 deliver HTTP POST requests to an HTTPS URL you configure whenever resources change.
Manage webhook configurations with the Platform API:

Setting up a webhook

Unlike API v1 (where create returned a signing key in the same response), API v2 setup is two calls:

  1. Create webhook — configure the HTTPS URL, optional alias, and inclusive filters (resource + eventTypes).
  2. 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}/keys

The 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 typeMeaning
CREATEDA new resource was created
UPDATEDAn existing resource changed
DELETEDA 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.

📘

About DELETED events

DELETED is sometimes used for data cleanup rather than a normal business process.
For example, booked transactions are not routinely deleted, but a rare cleanup (bank or Atlar side) may emit DELETED.

Resources you can subscribe to

Create webhooks with filters for these resources (API version 2 entity shapes):

ResourceTypical use
credit_transfersOutgoing payments
direct_debitsIncoming collections
mandatesDirect debit mandates
accountsBank accounts
account_end_of_day_summariesEnd-of-day account summaries
transactionsBooked transactions
pending_transactionsPending / intraday transactions
rolesIAM roles
membershipsOrganization memberships
invitationsUser invitations
audit_log_entriesAudit log entries
oauth_grantsOAuth grants

Note: New webhooks should use these API v2 resource names. In particular, use credit_transfers (not the legacy payments name), and do not create API v2 filters for expected_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 example credit_transfers)
  • apiVersion – major API version used to serialize entity (typically 2)
  • event – event metadata, including type (CREATED / UPDATED / DELETED), name, id, timestamp, and entityId
  • entity – 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 webhooks

Always process the snapshot in entity.
❗️Do not use only entity.id to make a separate GET for 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:

  1. Decode the key from standard Base64 into bytes.
  2. Build the signing input: request body (raw JSON bytes) + . + timestamp header value.
  3. Compute HMAC-SHA256 over that input.
  4. Encode the HMAC as a lowercase hex string.
  5. 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).
  6. 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.id as a unique key so duplicates are safe.
  • Ordering: Delivery is usually ordered but not guaranteed. Prefer entity.version (or event.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.


What’s Next

Did this page help you?