Webhooks
Webhooks let Rach CaaS push real-time event notifications to your server as transfer, deposit, and withdrawal statuses change — eliminating the need to poll the API.
Dashboard endpoints require a JWT Bearer token.
Base URL: https://rach-caas-api-dx75yvdhaq-nw.a.run.app
Managing Webhooks
Create Webhook
Registers a new webhook target URL. Rach will POST event payloads to this URL when state changes occur.
POST /v1/dashboard/webhooks
POST /v1/dashboard/webhooks
Authorization: Bearer <jwt>
Content-Type: application/json
{
"url": "https://your-app.com/webhooks/rach",
"secret": "whsec_your_signing_secret_here"
}| Field | Type | Required | Description |
|---|---|---|---|
url | string | ✅ | Your HTTPS endpoint to receive events |
secret | string | ✅ | Shared secret for HMAC signature verification |
List Webhooks
GET /v1/dashboard/webhooks
GET /v1/dashboard/webhooks
Authorization: Bearer <jwt>Delete Webhook
DELETE /v1/dashboard/webhooks/{id}
Deactivates a webhook target permanently.
List Webhook Logs
Returns granular logs of recent HTTP callback attempts, including response codes and retry history.
GET /v1/dashboard/webhooks/logs
GET /v1/dashboard/webhooks/logs
Authorization: Bearer <jwt>Event Types
| Event | Description |
|---|---|
deposit.settled | Fiat-to-crypto deposit confirmed on-chain |
transfer.queued | ERC-4337 UserOp queued |
transfer.submitted | UserOp submitted to Polygon mempool |
transfer.settled | Transfer confirmed on-chain |
withdrawal.submitted | USDC sweep initiated |
withdrawal.crypto_received | USDC received by Rach treasury |
withdrawal.completed | Local fiat disbursed to customer mobile money |
Payload Format
{
"event": "transfer.settled",
"timestamp": "2026-06-25T12:00:10Z",
"data": {
"transfer_id": "txn_abc123",
"status": "SETTLED",
"tx_hash": "0xPolygonTxHash...",
"settled_at": "2026-06-25T12:00:08Z"
}
}Signature Verification
Every webhook delivery includes a X-Rach-Signature header. Verify it using your shared secret to ensure the payload is authentic:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expectedSig = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return `sha256=${expectedSig}` === signature;
}
// In your webhook handler:
app.post('/webhooks/rach', (req, res) => {
const rawBody = req.rawBody; // must be raw bytes
const sig = req.headers['x-rach-signature'];
if (!verifyWebhook(rawBody, sig, process.env.RACH_WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(rawBody);
// Handle event...
res.status(200).send('OK');
});Retry Policy
If your endpoint returns a non-2xx response, Rach will retry delivery with exponential backoff. View all delivery attempts in GET /v1/dashboard/webhooks/logs.
