{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-products/direct-integration/guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["admonition","code-group"]},"type":"markdown"},"seo":{"title":"Configure webhooks","description":"Adfin's APIs for invoicing, payments and credit contol.","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"configure-webhooks","__idx":0},"children":["Configure webhooks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Configure a webhook by defining at least one endpoint and a list of events, and you're done. When you've set up a webhook, Adfin will notify you every time an event occurs for the object."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Prerequisites"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To proceed with this guide, you must have completed your webhook signature verification ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/products/direct-integration/guides/webhooks/webhook-signature-verification"},"children":["Webhook Signature Verification"]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"1-expose-an-endpoint-on-your-server","__idx":1},"children":["1. Expose an endpoint on your server"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Set up your endpoint to receive notifications. The endpoint should be a publicly accessible URL that can receive POST requests from Adfin. The event payload is sent in the request body."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Endpoint example:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["https://your-platform.com/webhook-endpoint"]}," ",{"$$mdtype":"Tag","name":"br","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"2-generate-a-client-access-token","__idx":2},"children":["2. Generate a client access token"]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Make sure you're using the correct access token type"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To use our webhooks API, generate an access token using the ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/api-docs/prod/oauth2/issueoauth2token"},"children":["client credentials flow"]},". ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["You will receive an error if using an access token generated during the authorization code flow"]},"."]}]},{"$$mdtype":"Tag","name":"br","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Get a platform access token with the ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/products/direct-integration/guides/get-started/authentication"},"children":["client credentials flow"]},", then use it as the Bearer token on every webhooks call below. Remember that your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_secret"]}," should be kept a secret: only use it to authenticate with the Adfin platform and don’t share it outside your organisation."]},{"$$mdtype":"Tag","name":"br","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"3-subscribe-to-webhooks","__idx":3},"children":["3. Subscribe to webhooks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Webhook subscription endpoint:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"POST /apps/{clientId}/webhooks\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This endpoint allows you to subscribe your platform to specific events from Adfin (e.g., ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["payment"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["dd-mandate"]},")."]},{"$$mdtype":"Tag","name":"CodeGroup","attributes":{"mode":"tabs"},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"curl","header":{"controls":{"copy":{}}},"source":"curl -X POST \"https://api.staging.adfin.com/api/apps/{clientId}/webhooks\" \\\n-H \"Authorization: Bearer your_platform_access_token\" \\\n-H \"Content-Type: application/json\" \\\n-d '{\n    \"url\": \"https://your-platform/adfin/status\",\n    \"events\": [\"payment\", \"invoice\", \"dd-mandate\"],\n    \"name\": \"webhook name\",\n    \"description\": \"webhook description\"\n}'\n","lang":"curl"},"children":[]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This cURL request will register your platform to receive webhook events, which can be used to handle real-time updates from Adfin (like payments being made or mandates being signed)​"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"response-example","__idx":4},"children":["Response example:"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the request is successful, Adfin responds with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["201 Created"]}," and the webhook it created."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"id\": \"29f6b7ea-94ed-4c3c-9655-b736216c798f\",\n  \"clientId\": \"{clientId}\",\n  \"url\": \"https://your-platform/adfin/status\",\n  \"name\": \"webhook name\",\n  \"description\": \"webhook description\",\n  \"events\": [\"payment\", \"invoice\", \"dd-mandate\"],\n  \"enabled\": true,\n  \"creationTime\": \"2025-12-15T10:30:00.000UTC\",\n  \"lastUpdatedTime\": \"2025-12-15T10:30:00.000UTC\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To change a webhook later, use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PUT /apps/{clientId}/webhooks/{webhookId}"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"security-best-practices","__idx":5},"children":["Security best practices"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Rotate secrets periodically"]},": Calling ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PUT /apps/{clientId}/webhooks/digest"]}," again generates a new signing key and returns it. There is no overlap period, and the switch is not instant: webhooks already queued, including retries, were signed with the old key, and some newly sent webhooks can still arrive signed with the old key for a while. Accept signatures from both keys until webhooks signed with the old key stop arriving."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Rate limiting"]},": Apply rate limits to your webhook endpoints to prevent abuse."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Logging"]},": Log all webhook verification failures and investigate unusual patterns of failed verification attempts."]}]}]},"headings":[{"value":"Configure webhooks","id":"configure-webhooks","depth":1},{"value":"1. Expose an endpoint on your server","id":"1-expose-an-endpoint-on-your-server","depth":2},{"value":"2. Generate a client access token","id":"2-generate-a-client-access-token","depth":2},{"value":"3. Subscribe to webhooks","id":"3-subscribe-to-webhooks","depth":2},{"value":"Response example:","id":"response-example","depth":3},{"value":"Security best practices","id":"security-best-practices","depth":2}],"frontmatter":{"seo":{"title":"Configure webhooks"}},"lastModified":"2026-10-02T15:25:13.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/products/direct-integration/guides/webhooks/webhook-setup","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}