sandbox.bankconnector.com API Reference

Webhooks

Audience: 🔌 Integration Client

BankConnector POSTs signed events to your endpoint as payments move through their lifecycle. This page covers managing and configuring endpoints. For the event envelope, signature verification, retries and the event catalog, see Receiving results. To post into Teams or Slack, see Teams and Slack webhook URLs.

Register an endpoint

curl -X POST https://sandbox.bankconnector.com/api/webhooks \
  -H "X-API-Key: $BC_KEY" -H "Content-Type: application/json" \
  -d '{
    "companyId":  "comp_…",
    "url":        "https://erp.example.com/hooks/bankconnector",
    "eventTypes": ["payment.sent", "payment.executed", "payment.rejected"]
  }'

The 201 body has two top-level keys, endpoint and secret. The endpoint id is at endpoint.id (there is no top-level id):

{
  "endpoint": {
    "id": "wh_…", // ← the id you pass to every /api/webhooks/<id>/… route
    "url": "https://erp.example.com/hooks/bankconnector",
    "eventTypes": ["payment.sent", "payment.executed", "payment.rejected"],
    "enabled": true,
    // …
  },
  "secret": "whsec_…", // ← the signing secret, shown ONCE
}

Read the id as body.endpoint.id. body.id is undefined.

FieldRequiredNotes
companyIdrequiredscope: the API key's own company
urlrequiredfor every transport, including slack and email; omitting it is a 400 url_required. Max 2048 chars. For the https transport it must be HTTPS (SSRF-guarded, IP-pinned)
eventTypesoptionalarray of event names. Omit (or send ["*"]) to receive every event in the catalog; an empty [] is rejected with a 400
transportoptional"https" (default), "slack", "teams", or "email"
emailTooptional (email)destination address for the email transport. Omit it and the event is emailed to the company's admins instead
filterPredicateoptional{ "bankKey": "danske-dk", "minAmount": 1000 }: deliver only matching events. minAmount/maxAmount are in EUR: an event in another currency is compared on its EUR equivalent at the cached reference rate, and one in a currency with no rate is delivered whatever its amount

Capture secret on creation: it's the whsec_… HMAC signing key and is shown only once. You verify every delivery against it (see Receiving results).

Unknown fields are rejected with 400 validation_failed.

If webhooks are not enabled for your organisation, registration answers 403 capability_disabled and no events are sent.

Managing endpoints

Method & pathWhat it does
GET /api/webhookslist your endpoints (metadata only, never the secret)
GET /api/webhooks/<id>fetch one endpoint
DELETE /api/webhooks/<id>remove an endpoint
POST /api/webhooks/<id>/enable, /disablepause / resume deliveries
POST /api/webhooks/<id>/testsend a webhook.test event through the real signing + delivery path
GET /api/webhooks/<id>/deliverieskeyset-paginated delivery attempts (newest first; see Pagination)
POST /api/webhooks/<id>/deliveries/<deliveryId>/redeliverreplay one delivery as a new attempt
POST /api/webhooks/<id>/redeliver-failed?since=<iso>bulk-replay every failed delivery since a timestamp
POST /api/webhooks/<id>/re-enableclear an auto-disabled endpoint (see below)
POST /api/webhooks/<id>/rotate-secretrotate the signing secret; body { "overlapHours": 24 } (default 24, clamped 1–72)

Managing webhooks needs an admin session or an API key (for the key's own company).

Reliability

  • Delivery is at-least-once, so deduplicate on the event id. Success is any HTTP 2xx; each attempt times out at 10 s.
  • 31 delivery attempts, exponential backoff 30 s → 1 m → 2 m → 4 m → 8 m → 16 m → 32 m → 1 h between them, then a flat 1 h wait for each of the 23 attempts after that, about 1443.5 minutes (roughly 24 hours) end to end (±20% jitter). After the 31st attempt the delivery settles failed; recover it with POST /api/webhooks/<id>/redeliver-failed?since=<iso> or the single-delivery redeliver above.
  • Circuit breaker: after 5 consecutive failed events an endpoint is auto-disabled and stops receiving until you POST /api/webhooks/<id>/re-enable. The webhook.auto-disabled transition is audit-log only (not itself a webhook), so back webhooks with a periodic poll and watch the X-Delivery-Sequence header for gaps.

Secret rotation

POST /api/webhooks/<id>/rotate-secret issues a new secret while keeping the old one valid for overlapHours. During the overlap, deliveries carry multiple v1= signatures (old and new): accept a match against any of them, then cut over to the new secret. See Receiving results.

Transports

  • HTTPS (default): a signed POST to your url.
  • Slack: set transport: "slack" and make url your Slack incoming-webhook URL.
  • Microsoft Teams: set transport: "teams" and make url your Teams Workflow webhook URL. Each event is posted as a card. Teams and Slack webhook URLs shows how to get either URL.
  • Email: set transport: "email" and (optionally) emailTo; events are formatted as email and go to the company's admins when emailTo is omitted. url is still required, although the email transport doesn't POST to it.