Webhook Setup
This guide explains how to set up and configure webhooks to receive notifications from Reap's compliance system.
Getting Started
To receive notifications when your account status changes, you need to register a webhook URL with Reap's notification system.
Available Event Types:
account_status_change- Notifications for account status updates including feature access changes
API Endpoints
Sandbox Environment
- Base URL:
https://sandbox-compliance.api.reap.global - Authentication:
x-reap-api-key: your-staging-key
Production Environment
- Base URL:
https://compliance.api.reap.global - Authentication:
x-reap-api-key: your-production-key
Webhook Operations
1. Register Your Webhook URL
Register your webhook URL to receive account status change notifications:
Using cURL:
curl -X POST <https://sandbox-compliance.api.reap.global/notification> \\
-H "accept: application/json" \\
-H "content-type: application/json" \\
-H "x-reap-api-key: your-staging-key" \\
-d '{
"webhookUrl": "<https://your-domain.com/webhooks/reap>",
"notificationChannel": "WEBHOOK",
"notificationTypes": [
"account_status_change"
]
}'
Using 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': 'your-staging-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));
Expected 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"
}
2. List Your Webhook Configurations
View all your configured webhooks:
curl -X GET <https://sandbox-compliance.api.reap.global/notification> \\
-H "accept: application/json" \\
-H "x-reap-api-key: your-staging-key"
3. Get a Specific Webhook Configuration
Retrieve details of a specific webhook:
curl -X GET <https://sandbox-compliance.api.reap.global/notification/{notificationId}> \\
-H "accept: application/json" \\
-H "x-reap-api-key: your-staging-key"
4. Update a Webhook Configuration
Update an existing webhook:
curl -X PUT <https://sandbox-compliance.api.reap.global/notification/{notificationId}> \\
-H "accept: application/json" \\
-H "content-type: application/json" \\
-H "x-reap-api-key: your-staging-key" \\
-d '{
"webhookUrl": "<https://your-updated-domain.com/webhooks/reap>",
"notificationChannel": "WEBHOOK",
"notificationTypes": [
"account_status_change"
]
}'
5. Delete a Webhook Configuration
Remove a webhook configuration:
curl -X DELETE <https://sandbox-compliance.api.reap.global/notification/{notificationId}> \\
-H "accept: application/json" \\
-H "x-reap-api-key: your-staging-key"
Webhook Security
Signature Verification
All webhook requests from Reap include a signature in the reap-signature header. This signature is generated using RSA-SHA512 to verify the authenticity of the request.
Public Keys for Signature Validation
Staging 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-----
Signature Verification Implementation
Here's how to verify webhook signatures in your application:
Node.js Example:
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');
}
// Use in your webhook handler
app.post('/webhooks/reap', (req, res) => {
const signature = req.headers['reap-signature'];
const publicKey = getPublicKeyForEnvironment(); // staging or production
if (!verifyWebhookSignature(req.body, signature, publicKey)) {
return res.status(401).send('Invalid signature');
}
// Process the webhook safely...
console.log('Webhook verified successfully');
res.status(200).send('OK');
});
function getPublicKeyForEnvironment() {
// Return the appropriate public key based on your environment
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-----`;
} else {
return `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsI0a/jqvSM6Z9gTLVMpD
4hLZ0n1WWuSNMwkqNH8s+E6tnBXx6nETgAJKwjdUagwgkySI74rwkCvPqVE0sm9c
iD8oi7XM+X8ybTET8fmVVG5sr12hJX5jQjjBUXzIuuqx5NJt7lFyo2yNrNzCSzuD
AhEa22Gkw43WWZoAVkNXlrfiyprKMfpjf7S4LUsRI/Y6MGyYmfm1olzYksymcaU+
2edfxoB2qZmezyEJM6CPkL2zt8UnnoS+kf/rbmHk+aKf8DW8v+XjeyQSxuclRZi/
IS589AACMygPvsO9KYzMoxmxNLrDcDnlo8+IKHQwE1RLoGC+EzJ0lDxWOEFZMRiE
xwIDAQAB
-----END PUBLIC KEY-----`;
}
}
Python Example:
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:
# Load the public key
public_key = serialization.load_pem_public_key(public_key_pem.encode())
# Decode the signature
signature_bytes = base64.b64decode(signature)
# Verify the signature
public_key.verify(
signature_bytes,
json.dumps(payload, separators=(',', ':')).encode(),
padding.PKCS1v15(),
hashes.SHA512()
)
return True
except Exception:
return False
# Use in your 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 webhook safely...
print('Webhook verified successfully')
return 'OK', 200
Webhook Requirements & Limitations
Technical Requirements
- HTTPS Required: Your webhook URL must use HTTPS
- Response Time: Respond with
200 OKwithin 5 seconds - Response Format: Simple
200 OKstatus code (response body is ignored)
Rate Limits & Constraints
- Webhook Limit: Each business is limited to 10 webhook configurations
- Retry Policy: Reap will retry failed webhook deliveries with exponential backoff
- Timeout: Requests will timeout after 5 seconds
Security Best Practices
- Always verify signatures before processing webhook data
- Use HTTPS for your webhook endpoints
- Validate incoming data structure and content
- Log webhook events for debugging and audit purposes
- Implement idempotency to handle duplicate deliveries
- Secure your API keys and rotate them regularly
Testing Your Webhook
1. Webhook URL Validation
Ensure your webhook endpoint:
- Returns
200 OKfor POST requests - Handles JSON payloads correctly
- Responds within 5 seconds
- Implements signature verification
2. Test Endpoint Example
// 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 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');
});
3. Testing Checklist
- Webhook URL is accessible via HTTPS
- Endpoint returns
200 OKfor valid requests - Signature verification is implemented and working
- Error handling is in place for invalid signatures
- Logging is configured for debugging
- Webhook registration via API is successful
Troubleshooting
Common Issues
Webhook Not Receiving Events
- Verify webhook URL is correctly registered
- Check that your endpoint is accessible from the internet
- Ensure HTTPS is properly configured
- Confirm you're subscribed to the correct event types (e.g.,
account_status_change)
Signature Verification Failing
- Verify you're using the correct public key for your environment
- Ensure you're signing the raw JSON payload (not parsed object)
- Check that the signature header name is exactly
reap-signature - Verify RSA-SHA512 algorithm is being used
Webhook Timeouts
- Ensure your endpoint responds within 5 seconds
- Consider processing webhooks asynchronously
- Implement proper error handling
Getting Help
If you encounter issues setting up webhooks:
- Check your webhook logs for error messages
- Verify API key permissions for your environment
- Test with a simple endpoint first
- Contact support with webhook registration details and error logs
For additional support, include:
- Your webhook URL
- The notification ID from registration
- Error messages or logs
- Environment (staging/production)
Updated 4 months ago
