HomeGuidesAPI ReferenceChangelog
Home
Guides

Webhook Setup


Purpose: Subscribe an integrator-controlled HTTPS endpoint to Reap's Compliance notification system, manage the webhook subscription lifecycle, and securely consume signed event payloads for the supported KYC verification flows.


ℹ️

The Notifications API is available only for the KYCaaS and Universal KYC verification methods. Webhook notifications are triggered exclusively for these two verification flows.

When to Use This

Use this guide when you need to:

  • Receive asynchronous KYC decision updates for cardholders onboarded via KYCaaS or Universal KYC
  • Register an HTTPS endpoint with Reap's Compliance API to consume the account_status_change event
  • Manage existing webhook subscriptions by listing, retrieving, updating, or deleting them
  • Verify the authenticity of incoming webhook payloads using Reap's RSA public key
  • Validate the integration in the sandbox environment before enabling webhook delivery in production

Overview

The Webhook Setup workflow registers an integrator-controlled HTTPS endpoint with Reap's Compliance API so that asynchronous events generated by the supported KYC flows can be delivered to the integrator's backend. Subscriptions are managed through the /notification resource, which supports the full lifecycle of a webhook configuration: registration, retrieval, update, and deletion.

Every webhook delivery is signed with Reap's RSA private key, allowing the integrator to verify the authenticity and integrity of the payload using the environment-specific RSA public key. Subscriptions are scoped to the business associated with the API key and apply to events generated for entities owned by that business.

The notification channel returns event payloads to a single subscribed URL per configuration, with the channel, subscribed event types, and webhook URL all returned in the registration response. Delivery is retried with exponential backoff when the integrator's endpoint fails to respond within the configured timeout.


Prerequisites

  1. An active Reap Compliance integration using either KYCaaS or Universal KYC for the program
  2. A sandbox API key generated from the Reap Card Issuance Dashboard and, once provisioned, a production API key linked to the integrator's business
  3. A publicly reachable HTTPS webhook endpoint capable of returning a 200 OK response within 5 seconds
  4. Reap's RSA public key for the relevant environment configured on the integrator side for webhook signature verification
  5. The ability to verify RSA-SHA512 signatures using the raw JSON payload received in the request body
⚠️

All Notifications API requests must be authenticated using the API key issued for the relevant environment. The business derived from the API key scopes every webhook configuration to the integrator's business.


Key Concepts

Notification Subscription

  • Webhook configuration registered against the Reap Compliance API at the /notification endpoint
  • Persisted under a unique notificationId returned at creation time and used in all subsequent management calls
  • Scoped to the business associated with the API key used at registration

Notification Channel

  • Delivery channel configured for the subscription
  • Webhook delivery is identified by notificationChannel: "WEBHOOK"

Notification Event Types

  • List of event types the subscription is registered for
  • Submitted as notificationTypes and currently supports account_status_change for account status updates including feature access changes

Webhook URL

  • HTTPS endpoint where Reap delivers signed event payloads via POST
  • Must be reachable from the public internet and able to respond with 200 OK within 5 seconds

Signature Verification

  • Every webhook request is signed by Reap using RSA-SHA512 and the signature is delivered in the reap-signature request header
  • The integrator verifies the signature against the raw JSON payload using the environment-specific RSA public key
  • Distinct public keys are issued for the sandbox and production environments

Webhook Configuration Limit

  • Each business may register up to 10 webhook configurations across all subscriptions

Flow Overview

  1. Generate sandbox and production API keys via the Reap Card Issuance Dashboard
  2. Provision a publicly reachable HTTPS endpoint configured to verify Reap's RSA-SHA512 signature
  3. Register the webhook endpoint via POST /notification and subscribe to the account_status_change event type
  4. Retrieve, update, or delete the webhook configuration via the /notification/notificationId endpoints as required
  5. Receive signed event payloads on the registered endpoint and verify each request using the environment-specific public key
  6. Validate the integration end to end in the sandbox environment before enabling the webhook configuration in production

API Summary

ActionEndpointMethodUse Case
Register webhook subscription/notificationPOSTRegister a webhook URL and subscribe to one or more notification event types
List webhook subscriptions/notificationGETRetrieve all webhook configurations registered for the business
Get a webhook subscription/notification/notificationIdGETRetrieve a single webhook configuration by notificationId
Update a webhook subscription/notification/notificationIdPUTUpdate the webhook URL, channel, or subscribed event types of an existing configuration
Delete a webhook subscription/notification/notificationIdDELETERemove an existing webhook configuration

Environment Endpoints

The Notifications API is environment-scoped and authenticated using the API key issued for that environment.

EnvironmentBase URLAuthentication Header
Sandboxhttps://sandbox-compliance.api.reap.globalx-reap-api-key: <sandbox-api-key>
Productionhttps://compliance.api.reap.globalx-reap-api-key: <production-api-key>
ℹ️

Use the sandbox API key and base URL throughout the integration and switch to the production API key and base URL only after the webhook integration has been validated end to end.


Webhook Setup

Step 1: Register a Webhook Subscription

Register an HTTPS endpoint with Reap's Compliance API to begin receiving asynchronous event notifications for the subscribed event types.


Call the Register Webhook Endpoint

Use POST /notification to register the webhook URL and subscribe it to one or more notification event types.


Sample Request (cURL)

curl --request POST \
  --url https://sandbox-compliance.api.reap.global/notification \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'x-reap-api-key: ********' \
  --data '{
    "webhookUrl": "https://your-domain.com/webhooks/reap",
    "notificationChannel": "WEBHOOK",
    "notificationTypes": ["account_status_change"]
  }'

Sample Request (JavaScript / Node.js)

const url = 'https://sandbox-compliance.api.reap.global/notification';
const options = {
  method: 'POST',
  headers: {
    accept: 'application/json',
    'content-type': 'application/json',
    'x-reap-api-key': '********',
  },
  body: JSON.stringify({
    webhookUrl: 'https://your-domain.com/webhooks/reap',
    notificationChannel: 'WEBHOOK',
    notificationTypes: ['account_status_change'],
  }),
};
 
fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));

Key Input

Parameter NameTypeDescription
notificationTypesarray of stringList of notification event types to subscribe to (e.g. account_status_change)

Sample Response

{
  "id": "notification-id-123",
  "channel": "WEBHOOK",
  "types": ["account_status_change"],
  "config": {
    "webhook": {
      "url": "https://your-domain.com/webhooks/reap"
    }
  },
  "createdAt": "2024-03-20T10:00:00Z"
}

Key Output

Parameter NameTypeDescription
idstringUnique identifier for the registered webhook subscription. Used as notificationId in all subsequent management calls
channelstringNotification delivery channel configured for the subscription (e.g. WEBHOOK)
typesarray of stringList of notification event types subscribed to
configobjectConfiguration details for the notification channel
config.webhook.urlstringWebhook endpoint URL where notification events will be delivered
createdAtstringTimestamp indicating when the notification subscription was created (Format: ISO 8601)
ℹ️

Each business is limited to a maximum of 10 webhook configurations. Additional registrations beyond this limit are rejected.


Step 2: List Webhook Subscriptions

Retrieve every webhook configuration registered against the business associated with the API key.


Call the List Webhook Subscriptions Endpoint

Use GET /notification to list all webhook configurations registered for the business.


Sample Request (cURL)

curl --request GET \
  --url https://sandbox-compliance.api.reap.global/notification \
  --header 'Accept: application/json' \
  --header 'x-reap-api-key: ********'

Key Input

Parameter NameTypeDescription
pageintegerQuery parameter specifying the page number to retrieve
limitintegerQuery parameter specifying number of records returned per page

Sample Response

{
  "items": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "channel": "WEBHOOK",
      "types": ["account_status_change"],
      "config": {
        "webhook": {
          "url": "https://api.example.com/webhooks/reap"
        }
      },
      "createdAt": "2024-03-20T10:00:00Z"
    }
  ],
  "meta": {
    "itemCount": 1,
    "totalItems": 1,
    "itemsPerPage": 10,
    "totalPages": 1,
    "currentPage": 1
  }
}

Key Output

Parameter NameTypeDescription
itemsarray of objectArray of notification configurations registered for the authenticated business
items[].idstringUnique identifier for the notification configuration
items[].channelstringNotification delivery channel configured for the subscription (e.g. WEBHOOK)
items[].typesarray of stringList of notification event types subscribed to
items[].configobjectChannel-specific configuration. For webhooks, contains the webhook.url property
items[].config.webhook.urlstringWebhook endpoint URL where notification events will be delivered
items[].createdAtstringTimestamp indicating when the notification configuration was created (Format: ISO 8601)
metaobjectPagination metadata for the returned result set

meta (object)

Parameter NameTypeDescription
itemCountnumberNumber of records returned on the current page
totalItemsnumberTotal number of notification configurations available
itemsPerPagenumberMaximum number of records returned per page
totalPagesnumberTotal number of pages available
currentPagenumberCurrent page number returned in the response

Step 3: Get a Webhook Subscription

Retrieve the details of a single webhook configuration by its notificationId.


Call the Get Webhook Subscription Endpoint

Use GET /notification/notificationId to retrieve the configuration of a single webhook subscription.


Sample Request (cURL)

curl --request GET \
  --url https://sandbox-compliance.api.reap.global/notification/notificationId \
  --header 'Accept: application/json' \
  --header 'x-reap-api-key: ********'

Key Input

Parameter NameTypeDescription
notificationIdstringPath parameter specifying the UUID of the webhook subscription to retrieve as returned during registration

Sample Response

{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "channel": "WEBHOOK",
  "types": ["account_status_change"],
  "config": {
    "webhook": {
      "url": "https://api.example.com/webhooks/reap"
    }
  },
  "createdAt": "2024-03-20T10:00:00Z"
}

Key Output

Parameter NameTypeDescription
idstringUnique identifier for the notification configuration
channelstringNotification delivery channel configured for the subscription (e.g. WEBHOOK)
typesarray of stringList of notification event types subscribed to
configobjectChannel-specific configuration for webhooks containing the webhook.url property
config.webhook.urlstringWebhook endpoint URL where notification events will be delivered
createdAtstringTimestamp indicating when the notification configuration was created (Format: ISO 8601)

Step 4: Update a Webhook Subscription

Update an existing webhook configuration to change the destination URL, channel, or subscribed event types.


Call the Update Webhook Subscription Endpoint

Use PUT /notification/notificationId to update an existing webhook configuration.


Sample Request (cURL)

curl --request PUT \
  --url https://sandbox-compliance.api.reap.global/notification/notificationId \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'x-reap-api-key: ********' \
  --data '{
    "webhookUrl": "https://your-updated-domain.com/webhooks/reap",
    "notificationChannel": "WEBHOOK",
    "notificationTypes": ["account_status_change"]
  }'

Key Input

Parameter NameTypeDescription
webhookUrlstringUpdated HTTPS URL where Reap will deliver event payloads. Must be publicly accessible

Sample Response

{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "channel": "WEBHOOK",
  "types": ["account_status_change"],
  "config": {
    "webhook": {
      "url": "https://api.example.com/webhooks/reap/updated"
    }
  },
  "createdAt": "2024-03-20T10:00:00Z"
}

Key Output

Parameter NameTypeDescription
idstringUnique identifier for the notification configuration
channelstringNotification delivery channel configured for the subscription (e.g. WEBHOOK)
typesarray of stringList of notification event types subscribed to
configobjectChannel-specific configuration for webhooks containing the webhook.url property
config.webhook.urlstringUpdated webhook endpoint URL where notification events will be delivered
createdAtstringTimestamp indicating when the notification configuration was created (Format: ISO 8601)

Step 5: Delete a Webhook Subscription

Remove an existing webhook configuration so Reap stops delivering events to the registered URL.


Call the Delete Webhook Subscription Endpoint

Use DELETE /notification/notificationId to remove an existing webhook configuration.


Sample Request (cURL)

curl --request DELETE \
  --url https://sandbox-compliance.api.reap.global/notification/notificationId \
  --header 'Accept: application/json' \
  --header 'x-reap-api-key: ********'

Key Input

Parameter NameTypeDescription
notificationIdstringPath parameter specifying the UUID of the webhook subscription to delete

Sample Response

No Content
ℹ️

A successful deletion returns 204 No Content with an empty response body. Once deleted, Reap stops delivering events to the previously registered URL and the notificationId can no longer be retrieved via GET /notification/notificationId.


Step 6: Verify the Webhook Signature

Every webhook request delivered by Reap includes a signature in the reap-signature header generated using RSA-SHA512. The integrator must verify each request against the raw JSON payload using the environment-specific RSA public key before processing the event.


Signature Algorithm

PropertyValue
AlgorithmRSA-SHA512
Signature headerreap-signature
Signed contentRaw JSON request body delivered by Reap
EncodingBase64-encoded signature value

Public Keys for Signature Validation

Use the public key matching the environment from which the webhook is delivered.

Sandbox Public Key

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsI0a/jqvSM6Z9gTLVMpD
4hLZ0n1WWuSNMwkqNH8s+E6tnBXx6nETgAJKwjdUagwgkySI74rwkCvPqVE0sm9c
iD8oi7XM+X8ybTET8fmVVG5sr12hJX5jQjjBUXzIuuqx5NJt7lFyo2yNrNzCSzuD
AhEa22Gkw43WWZoAVkNXlrfiyprKMfpjf7S4LUsRI/Y6MGyYmfm1olzYksymcaU+
2edfxoB2qZmezyEJM6CPkL2zt8UnnoS+kf/rbmHk+aKf8DW8v+XjeyQSxuclRZi/
IS589AACMygPvsO9KYzMoxmxNLrDcDnlo8+IKHQwE1RLoGC+EzJ0lDxWOEFZMRiE
xwIDAQAB
-----END PUBLIC KEY-----

Production Public Key

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5JUURpniA359qJLwB9JW
6tFAhc4ChqBiGSBaFTkgmK/XCrV8e/N7q57qq4DwymDk5+ALw8D6cKeG2QkWPDeB
n3ly96sR14+8+2GfS7z82A194V9xEpZQfjF6DeMhidFjhINAAzJHPDiM7QCk9Dh4
/Ny065vzZb0O3ek9Ivs6sbmOKXa/pGACN3k30XLkPu2XxBfeZN1rCFhdwE/wa7Bf
h5AKiA104ais19ct5uf4vNkjG5DwevFK9WiqRVxwzadOyXCk4AdksdFx8ZkOuYWh
rCdIt3Dc+pErfKIHloJ7kqA/8kiWWOP6fWbSSWrEtpLX5ieVsXnqhOYq8xA5WvEo
HwIDAQAB
-----END PUBLIC KEY-----

Sample Verification Implementation (Node.js)

const crypto = require('crypto');
 
function verifyWebhookSignature(payload, signature, publicKey) {
  const verifier = crypto.createVerify('RSA-SHA512');
  verifier.update(JSON.stringify(payload));
  verifier.end();
 
  return verifier.verify(publicKey, signature, 'base64');
}
 
// Webhook handler
app.post('/webhooks/reap', (req, res) => {
  const signature = req.headers['reap-signature'];
  const publicKey = getPublicKeyForEnvironment(); // sandbox or production
 
  if (!verifyWebhookSignature(req.body, signature, publicKey)) {
    return res.status(401).send('Invalid signature');
  }
 
  // Process the verified event
  console.log('Webhook verified successfully');
  res.status(200).send('OK');
});
 
function getPublicKeyForEnvironment() {
  if (process.env.NODE_ENV === 'production') {
    return `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5JUURpniA359qJLwB9JW
6tFAhc4ChqBiGSBaFTkgmK/XCrV8e/N7q57qq4DwymDk5+ALw8D6cKeG2QkWPDeB
n3ly96sR14+8+2GfS7z82A194V9xEpZQfjF6DeMhidFjhINAAzJHPDiM7QCk9Dh4
/Ny065vzZb0O3ek9Ivs6sbmOKXa/pGACN3k30XLkPu2XxBfeZN1rCFhdwE/wa7Bf
h5AKiA104ais19ct5uf4vNkjG5DwevFK9WiqRVxwzadOyXCk4AdksdFx8ZkOuYWh
rCdIt3Dc+pErfKIHloJ7kqA/8kiWWOP6fWbSSWrEtpLX5ieVsXnqhOYq8xA5WvEo
HwIDAQAB
-----END PUBLIC KEY-----`;
  }
  return `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsI0a/jqvSM6Z9gTLVMpD
4hLZ0n1WWuSNMwkqNH8s+E6tnBXx6nETgAJKwjdUagwgkySI74rwkCvPqVE0sm9c
iD8oi7XM+X8ybTET8fmVVG5sr12hJX5jQjjBUXzIuuqx5NJt7lFyo2yNrNzCSzuD
AhEa22Gkw43WWZoAVkNXlrfiyprKMfpjf7S4LUsRI/Y6MGyYmfm1olzYksymcaU+
2edfxoB2qZmezyEJM6CPkL2zt8UnnoS+kf/rbmHk+aKf8DW8v+XjeyQSxuclRZi/
IS589AACMygPvsO9KYzMoxmxNLrDcDnlo8+IKHQwE1RLoGC+EzJ0lDxWOEFZMRiE
xwIDAQAB
-----END PUBLIC KEY-----`;
}

Sample Verification Implementation (Python)

import json
import base64
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
 
def verify_webhook_signature(payload, signature, public_key_pem):
    try:
        public_key = serialization.load_pem_public_key(public_key_pem.encode())
        signature_bytes = base64.b64decode(signature)
 
        public_key.verify(
            signature_bytes,
            json.dumps(payload, separators=(',', ':')).encode(),
            padding.PKCS1v15(),
            hashes.SHA512()
        )
        return True
    except Exception:
        return False
 
# Flask webhook handler
@app.route('/webhooks/reap', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('reap-signature')
    public_key = get_public_key_for_environment()
 
    if not verify_webhook_signature(request.json, signature, public_key):
        return 'Invalid signature', 401
 
    # Process the verified event
    print('Webhook verified successfully')
    return 'OK', 200
⚠️

Always verify the signature against the original JSON payload received in the request body and not against a reconstructed object. Reconstructing the payload may alter key ordering or whitespace and cause verification to fail.


Webhook Endpoint Requirements

The webhook endpoint registered with Reap must comply with the following requirements.


Technical Requirements

RequirementDetail
ProtocolHTTPS is required for all webhook endpoints
Response statusThe endpoint must return 200 OK for successfully received events
Response timeThe endpoint must respond within 5 seconds
Response bodyThe response body is ignored — only the 200 OK status code is required
Signature verificationVerify the webhook signature using Reap's RSA public key for the relevant environment
Environment validationValidate the endpoint in the sandbox environment before enabling the webhook subscription in production

Rate Limits and Constraints

ConstraintLimit
Maximum subscriptionsUp to 10 webhook configurations per business
Endpoint response timeout5 seconds per delivery attempt
Retry policyFailed deliveries are retried using exponential backoff

Security Best Practices

  1. Always verify the signature before processing webhook data
  2. Use HTTPS for the webhook endpoint and present a valid TLS certificate
  3. Validate the structure and content of every incoming payload
  4. Log every webhook event for debugging and audit purposes
  5. Implement idempotency at the consumer to safely handle duplicate deliveries from retries
  6. Secure the API keys used for subscription management and rotate them regularly

Testing Your Webhook

Validate the webhook integration end to end in the sandbox environment before enabling delivery in production.

Webhook Endpoint Validation

The webhook endpoint must:

  • Be reachable from the public internet via HTTPS
  • Return 200 OK for valid POST requests
  • Handle JSON request payloads correctly
  • Respond within 5 seconds
  • Implement RSA-SHA512 signature verification using the sandbox public key

Sample Test Endpoint

// Simple test endpoint
app.post('/webhooks/reap', (req, res) => {
  console.log('Received webhook:', JSON.stringify(req.body, null, 2));
  console.log('Headers:', req.headers);
 
  // Always verify the signature in production
  const signature = req.headers['reap-signature'];
  if (signature && !verifyWebhookSignature(req.body, signature, publicKey)) {
    return res.status(401).send('Invalid signature');
  }
 
  res.status(200).send('OK');
});

Testing Checklist

  • Webhook URL is reachable over HTTPS from the public internet
  • Endpoint returns 200 OK for valid POST requests within 5 seconds
  • Signature verification is implemented using the environment-specific public key
  • Error handling rejects requests with an invalid or missing signature
  • Logging is configured for incoming requests and verification outcomes
  • Webhook registration via POST /notification returned a successful response

Scenarios

Scenario: First-Time Webhook Setup

  • Generate a sandbox API key from the Reap Card Issuance Dashboard
  • Provision an HTTPS endpoint and configure the sandbox public key for signature verification
  • Register the webhook via POST /notification subscribing to account_status_change
  • Validate end-to-end delivery in the sandbox environment
  • Repeat the registration in production using the production API key and production public key

Scenario: Update the Webhook URL

  • Retrieve the existing configuration via GET /notification/notificationId
  • Update the destination via PUT /notification/notificationId with the new webhookUrl
  • Confirm signature verification continues to succeed against the same environment public key

Scenario: Remove a Webhook Subscription

  • Remove the configuration via DELETE /notification/notificationId to stop event delivery
  • Confirm via GET /notification that the subscription is no longer listed

Common Errors

ErrorCauseResolution
Webhook not receiving eventsEndpoint unreachable, HTTPS misconfigured, or subscribed to the wrong event typeConfirm the endpoint is reachable over HTTPS and the subscription includes account_status_change
Signature verification failingWrong environment public key, parsed payload re-serialised, or incorrect signature headerVerify against the raw JSON body using the matching environment public key and read the reap-signature header
Webhook timeoutEndpoint did not return 200 OK within 5 secondsProcess webhook events asynchronously and return 200 OK immediately after receipt
401 UnauthorizedMissing or invalid API key when calling the /notification endpointsCheck x-reap-api-key and confirm the API key matches the environment
Webhook configuration limit reachedBusiness already has 10 webhook configurations registeredDelete an unused configuration via DELETE /notification/notificationId before registering a new one

TL;DR

  • Webhooks are available only for the KYCaaS and Universal KYC verification methods and currently support the account_status_change event type
  • Register a webhook via POST /notification with webhookUrl, notificationChannel: "WEBHOOK", and notificationTypes: ["account_status_change"]
  • Manage subscriptions via GET /notification, GET /notification/notificationId, PUT /notification/notificationId, and DELETE /notification/notificationId
  • Webhook endpoints must use HTTPS and return 200 OK within 5 seconds, and failed deliveries are retried with exponential backoff
  • Verify every request using RSA-SHA512 against the raw JSON body and the environment-specific public key from the reap-signature header
  • Each business is limited to a maximum of 10 webhook configurations
  • Validate the webhook integration in the sandbox environment before enabling delivery in production

Support

📘

Contact your Reap Implementation Manager for any webhook setup, signature verification, or delivery issues. Include the webhook URL, the notificationId returned at registration, the environment (sandbox or production), and any relevant error messages or logs when raising a support request.