sandbox.bankconnector.com API Reference

Webhooks

Audience: 🔌 Integration Client

BankConnector POSTs signed events to your endpoint as payments move through their lifecycle. This page is the management + configuration reference. For the receiver side (the event envelope, signature verification, retries, and the full event catalog), see Receiving Results.

Register an endpoint

curl -X POST https://sandbox.bankconnector.com/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 /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. If you store body.id you'll persist undefined and be unable to rotate, disable, or delete the endpoint later.

FieldRequiredNotes
companyIdrequiredscope (platform is inferred from the API key)
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 to receive all events; an explicitly-empty [] is rejected (a 400, so a typo like events: can't silently subscribe you to everything)
transportoptional"https" (default), "slack", 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

Capture secret on creation: it's the whsec_… HMAC signing key and is shown only once. Store it in your secret manager; you verify every delivery against it (see Receiving Results).

Unknown fields are rejected (400 validation_failed), so a typo can't be silently ignored.

Managing endpoints

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

Managing webhooks needs an admin session or a platform API key.

Reliability at a glance

  • At-least-once, so deduplicate on the event id. Success is any HTTP 2xx; each attempt times out at 10 s.
  • 8 delivery attempts with exponential backoff (30 s → 1 h, ±20% jitter).
  • Circuit breaker: after 5 consecutive failed events an endpoint is auto-disabled and stops receiving until you POST /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 /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 + new): accept a match against any of them, then cut over to the new secret. See Receiving Results.

Transports

url is required on every transport — the create route rejects a body without one (400 url_required) before it even looks at transport.

  • HTTPS (default): a signed POST to your url.
  • Slack: set transport: "slack" and make url your Slack incoming-webhook URL; events are formatted as Slack messages.
  • Email: set transport: "email" and (optionally) emailTo; events are formatted as email, and go to the company's admins when emailTo is omitted. A url is still required by the route, even though the email transport doesn't POST to it.