Webhooks

Receive real-time notifications when events occur in your Open Banking integration—consent changes, payment status updates, and account activity.

Overview

Webhooks allow your application to receive push notifications about events instead of polling the API. When an event occurs, we send an HTTP POST request to your configured endpoint with details about the event.

HTTPS Required

Webhook endpoints must use HTTPS in production. HTTP endpoints are only accepted in the sandbox environment.

Event Types

Subscribe to specific event types based on your integration needs:

Consent Events

Triggered when consent status changes. Essential for tracking authorization flow completion.

Event TypeDescriptionWhen Triggered
consent.authorizedConsent was authorized by the PSUUser completes consent approval
consent.rejectedConsent was rejected by the PSUUser denies consent request
consent.revokedConsent was revokedUser or TPP revokes active consent
consent.expiredConsent has expiredConsent passes its expiration date

Payment Events

Triggered during payment lifecycle. Use these to update your UI and notify users.

Event TypeDescriptionWhen Triggered
payment.createdPayment initiation was createdPOST /payments succeeds
payment.completedPayment was successfully executedFunds transfer completes
payment.failedPayment execution failedInsufficient funds, validation error, etc.

Account Activity Events

Real-time notifications for account changes. Requires active account-access consent.

Event TypeDescriptionWhen Triggered
transaction.postedNew transaction posted to accountDebit or credit posts
balance.updatedAccount balance changedAfter transaction posting

Scheduled Payment Events

Notifications for standing orders and scheduled payments.

Event TypeDescriptionWhen Triggered
schedule.createdScheduled payment was createdNew standing order set up
schedule.executedScheduled payment was executedRecurring payment runs successfully
schedule.failedScheduled payment failedRecurring payment fails
schedule.cancelledScheduled payment was cancelledStanding order cancelled

Webhook Payload

All webhook payloads follow a consistent structure:

{
  "id": "evt_1234567890abcdef",
  "type": "payment.completed",
  "timestamp": "2024-01-15T10:30:00Z",
  "resource_id": "pay_abc123",
  "resource_type": "payment",
  "data": {
    "payment_id": "pay_abc123",
    "status": "completed",
    "amount": {
      "amount": "100.00",
      "currency": "GBP"
    },
    "creditor_account": {
      "scheme": "SortCodeAccountNumber",
      "identification": "608371-12345678"
    }
  }
}

Payload Fields

FieldTypeDescription
idstringUnique event identifier (for idempotency)
typestringEvent type (e.g., payment.completed)
timestampstringISO 8601 timestamp when event occurred
resource_idstringID of the affected resource
resource_typestringType of resource (consent, payment, account)
dataobjectEvent-specific payload data

Request Headers

Each webhook request includes these headers for verification and debugging:

HeaderDescriptionExample
Content-TypeAlways application/jsonapplication/json
User-AgentIdentifies the webhook senderHamsterBank-Webhooks/1.0
X-Webhook-IDYour webhook subscription IDwhk_abc123
X-Event-IDUnique event IDevt_xyz789
X-Event-TypeEvent type for routingpayment.completed
X-Webhook-SignatureHMAC-SHA256 signaturea1b2c3d4...
X-Webhook-TimestampRequest timestamp2024-01-15T10:30:00Z

Signature Verification

Every webhook request is signed using HMAC-SHA256. Always verify signatures to ensure requests originate from Hamster Bank and haven't been tampered with.

Security Critical

Never process webhook payloads without verifying the signature. Attackers could send fake events to manipulate your system.

Verification Steps

  1. Extract the signature from the X-Webhook-Signature header
  2. Compute HMAC-SHA256 of the raw request body using your webhook secret
  3. Compare signatures using a constant-time comparison function
  4. Reject requests with invalid signatures

Example (Go)

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
)

func verifySignature(payload []byte, signature, secret string) bool {
    h := hmac.New(sha256.New, []byte(secret))
    h.Write(payload)
    expected := hex.EncodeToString(h.Sum(nil))
    return hmac.Equal([]byte(expected), []byte(signature))
}

func webhookHandler(w http.ResponseWriter, r *http.Request) {
    signature := r.Header.Get("X-Webhook-Signature")
    body, _ := io.ReadAll(r.Body)
    
    if !verifySignature(body, signature, os.Getenv("WEBHOOK_SECRET")) {
        http.Error(w, "Invalid signature", http.StatusUnauthorized)
        return
    }
    
    // Process the verified webhook...
    w.WriteHeader(http.StatusOK)
}

Example (Node.js)

const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

app.post('/webhooks', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  
  if (!verifySignature(req.body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  const event = JSON.parse(req.body);
  // Process the verified webhook...
  res.status(200).send('OK');
});

Retry Behavior

If your endpoint doesn't respond with a 2xx status code within 10 seconds, we'll retry delivery with exponential backoff:

AttemptDelay After FailureCumulative Time
1Immediate
230 seconds30 seconds
31 minute~1.5 minutes
42 minutes~3.5 minutes
54 minutes~7.5 minutes

After 5 failed attempts, the delivery is marked as abandoned. If a webhook consistently fails (10+ consecutive failures), it will be automatically disabled.

Best Practice

Respond to webhooks quickly (within 5 seconds) with a 200 status. Process the event asynchronously using a job queue if needed.

Best Practices

1. Respond Immediately

Return a 200 response as soon as you receive the webhook. Queue the event for async processing to avoid timeouts.

2. Handle Duplicates

Use the event ID for idempotency. Store processed event IDs and skip duplicates—we may retry even after successful delivery in rare cases.

3. Verify Signatures

Always verify the HMAC-SHA256 signature before processing. This prevents attackers from forging webhook events.

4. Handle Event Ordering

Events may arrive out of order. Use the timestamp field and resource state to handle this gracefully.

5. Monitor Your Endpoint

Set up alerting for webhook failures. Check the developer dashboard for delivery status and error details.

Error Handling

Your endpoint should return appropriate status codes:

Status CodeMeaningOur Action
200-299SuccessMark as delivered
4xxClient error (bad request)Retry (may be transient)
5xxServer errorRetry with backoff
TimeoutNo response within 10sRetry with backoff