Webhooks â Real-Time Updates
Subscribe to events and verify webhook signatures.
Why webhooks?
Instead of polling the API for changes, webhooks deliver real-time HTTP POST notifications when events occur. This lets you trigger downstream actions (updating your ERP, notifying your team) immediately when a payment changes state.
How it works
- 1.You configure a webhook URL via the API
- 2.Atlar sends HTTP POST to that URL whenever a matching event occurs
- 3.Your server processes the payload and responds with
200 OK - 4.If delivery fails, Atlar retries 3 times every 15 minutes for up to 12 hours
Create a webhook
/v1/webhooksSubscribe to events. Specify resource types and event names in the filter array.
curl -X POST 'https://api.atlar.com/v1/webhooks' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Payment updates",
"url": "https://your-server.example.com/webhooks/atlar",
"filter": [
{
"apiVersion": 1,
"resource": "credit_transfers",
"events": ["CREATED", "UPDATED"]
},
{
"apiVersion": 1,
"resource": "transactions",
"events": ["CREATED"]
}
]
}'Testing without a server
Use webhook.site or Pipedream to get a temporary URL that displays incoming webhook payloads in real time.
Webhook payload
Each webhook delivers the resource in its state after the event. The payload includes event metadata and the full entity:
{
"resource": "credit_transfers",
"apiVersion": 1,
"event": {
"organizationId": "1f91e001-...",
"entityId": "422a164c-...",
"id": 3,
"timestamp": "2025-11-06T07:26:56.837Z",
"name": "UPDATED",
"originator": "90b51164-..."
},
"entity": {
"id": "422a164c-...",
"status": "APPROVED",
"amount": { "currency": "EUR", "value": 2500 },
...
}
}Event types
| Event | Description |
|---|---|
CREATED | A new resource was created |
UPDATED | An existing resource was modified (e.g. status change) |
DELETED | A resource was removed (rare, typically data cleanup) |
Webhook security
Atlar sends two headers with each webhook for verification:
| Header | Format | Purpose |
|---|---|---|
Webhook-Signature | HMAC-SHA256 hex | Verify authenticity and integrity |
Webhook-Request-Timestamp | RFC 3339 UTC | Prevent replay attacks |
Signature verification
The signature is computed as HMAC-SHA256(key, body + "." + timestamp). To verify:
- 1. Base64-decode the webhook key into bytes
- 2. Concatenate:
body + "." + timestamp - 3. Compute HMAC-SHA256
- 4. Hex-encode and compare using constant-time comparison
- 5. Check the timestamp is recent (within ~5 minutes)
import hmac, hashlib, base64
def verify_webhook(body: str, timestamp: str, signature: str, base64_key: str) -> bool:
"""Verify an Atlar webhook signature."""
key = base64.b64decode(base64_key)
message = f"{body}.{timestamp}".encode()
expected = hmac.new(key, message, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
# Usage in your webhook handler:
# is_valid = verify_webhook(
# body=request.body.decode(),
# timestamp=request.headers["Webhook-Request-Timestamp"],
# signature=request.headers["Webhook-Signature"],
# base64_key="your-webhook-key-from-creation",
# )Webhook best practices
- Always verify the HMAC signature before processing.
- Use constant-time comparison to prevent timing attacks.
- Make your handler idempotent â duplicate deliveries are possible.
- Respond with
200 OKquickly; do heavy processing asynchronously. - Use
event.id+entity.idto deduplicate events. - Rotate webhook keys if compromised via
/v1/webhooks/{id}/keys.
Going live
Before receiving production webhooks, your endpoint must be verified by Atlar. Contact support@atlar.com to verify your webhook URL. Note: modifying the URL resets verification.