Webhooks
Webhooks allow your own applications or third-party services like Zapier to receive real-time notifications whenever something happens in your Synci account. Instead of polling our API for updates, Synci "pushes" the data to your URL as it occurs.
Written By Matias
Last updated 6 days ago
Configuring Webhook Endpoints
You can manage your webhooks through the Synci Dashboard under Developers > Webhooks or via the /api/v1/webhook-endpoints API endpoints.
Key Configuration Options
Endpoint URL: The HTTPS URL where Synci will send the POST requests.
Events: Choose exactly which types of events you want to receive.
Bank account filtering: Optionally restrict a webhook to only trigger for specific bank accounts.
Omit sensitive identifiers: When enabled, Synci will strip IBANs, BBANs, and other sensitive identifiers from the payload. This is required for Zapier integrations.
Signing secret: A unique
whsec_key used to verify that the request came from Synci. Automatically generated by Synci as you create a new webhook endpoint, and only shown once.
Event types & payload examples
All webhooks follow a standard wrapper structure:
{
"event_type": "transactions.created",
"event_id": "evt_8723456789",
"webhook_endpoint_id": "endpoint_123456",
"created_at": "2024-03-20T10:00:00Z",
"data": { ... }
}Transactions
transactions.created & transactions.updated
Triggered when new transactions are fetched or their status changes.
{
"event_type": "transactions.created",
"event_id": "evt_123",
"data": {
"bank_account": {
"id": "acc_550",
"name": "Main Checking",
"currency": "EUR",
"iban": "DE12345678901234567890"
},
"transactions": [
{
"id": "tx_999",
"amount": -42.50,
"currency": "EUR",
"booked": true,
"generated": {
"date": "2024-03-20",
"payee": "Coffee Shop",
"description": "Coffee Shop Berlin"
},
"booking_date": "2024-03-20",
"remittance_information": {
"unstructured": "CARD PURCHASE COFFEE SHOP"
}
}
]
}
}Balance
balance.updated
Triggered when your bank account balance changes.
{
"event_type": "balance.updated",
"event_id": "evt_456",
"data": {
"bank_account": {
"id": "acc_550",
"name": "Main Checking",
"currency": "EUR"
},
"balance": {
"available": 1250.75,
"cleared": 1200.00
}
}
}Bank account
bank_account.created, bank_account.updated, bank_account.deleted
Triggered when account configurations or status change.
{
"event_type": "bank_account.updated",
"event_id": "evt_789",
"data": {
"id": "acc_550",
"name": "Main Checking",
"display_name": "My Daily Expenses",
"enabled": true,
"currency": "EUR",
"integrator": "GOCARDLESS",
"balance": {
"available": 1250.75,
"cleared": 1200.00
}
}
}Testing webhooks
Building a reliable webhook integration requires thorough testing. Synci provides built-in tools to simulate events and verify how your application handles them, using either dummy data or real information from your connected accounts.
Triggering test events
You can trigger a test event in two ways.
Via the dashboard
Navigate to Developers > Webhooks, select your endpoint, and go to the "Test" tab. You can select the event type and an optional bank account to use for real data.

Via the API
Send a POST request to /api/v1/webhook-endpoints/{endpointId}/test. Include event (required) and bank_account_id (optional) in the JSON body.
Real data vs. dummy data
Real data: By selecting a bank account, Synci will pull the latest 2 transactions or the current balance from that account to populate the test payload. This is highly recommended for verifying that your field mapping matches your specific bank's data structure.
Dummy data: If no bank account is specified, Synci generates placeholder transactions and balances. This is useful for initial development and verifying signature validation.
Key testing rules
Rate limits: Testing is limited to 5 requests per minute per endpoint.
No retries: Unlike production events, test events are only sent once. If your server is down during a test, you must trigger a new test manually.
Event override: You can test any event type, even if it is not currently enabled in your webhook's settings.
Security: Verifying signatures
To ensure that a webhook was actually sent by Synci, you should verify the X-Synci-Signature HTTP header. This signature is an HMAC-SHA256 hash of the raw request body using your Signing Secret.
How to verify
Capture the raw request body.
Compute an HMAC-SHA256 hash of the raw body using your Signing Secret as the key.
Compare your computed hash with the value in the
X-Synci-Signatureheader. If they match, the request is authentic.
Examples
Example$secret = 'whsec_your_secret';
$signature = $_SERVER['HTTP_X_SYNCI_SIGNATURE'];
$payload = file_get_contents('php://input');
$computedSignature = hash_hmac('sha256', $payload, $secret);
if (hash_equals($signature, $computedSignature)) {
// Authenticated
}Rotating the signing secret
If you’ve lost a webhook signing secret, you can generate a new one by opening your webhook endpoint, and clicking “Rotate Secret”.

You can also rotate a webhook signing secret through the API, by sending a POST request to /api/v1/webhook-endpoints/{endpointId}/rotate-secret.
Delivery & retry logic
Retries: If the delivery fails (non-2xx status), Synci will retry up to 3 times.
Exponential backoff: Retries occur at 1 minute, 10 minutes, and 1 hour intervals.
Automatic disabling: If an endpoint returns a
410 Goneor fails persistently, it will be automatically disabled to protect the system.
Pro tips
Acknowledge quickly: Return a
2xxstatus code immediately and process the data asynchronously (e.g., using a queue).Idempotency: Use the
event_idto ignore duplicate notifications that might occur during retries.Zapier: Ensure "Omit Sensitive Identifiers" is ON for Zapier to ensure data compatibility.