Skip to main content
Webhooks are HTTP callbacks that RemitFlex sends to your server when something happens — a payment delivers, a conversion completes, or a compliance review is triggered. Instead of polling the API for status changes, you register an endpoint and RemitFlex pushes events to you in real time.

Register your webhook endpoint

Add your endpoint URL in the RemitFlex dashboard:
1
Open the Webhooks settings
2
Go to Dashboard → Settings → Webhooks and click Add endpoint.
3
Enter your endpoint URL
4
Provide a publicly accessible HTTPS URL on your server (for example, https://api.yourapp.com/webhooks/remitflex). RemitFlex does not support plain HTTP endpoints.
5
Select the events to receive
6
Choose specific event types or select Receive all events to subscribe to everything.
7
Save and copy your webhook secret
8
After saving, RemitFlex displays a signing secret for this endpoint. Copy it now — you’ll use it to verify incoming request signatures. It is shown only once.
You can register multiple endpoints and subscribe different endpoints to different event subsets. This is useful for separating payment notifications from compliance alerts.

Supported event types

EventTriggered when
payment.createdA new payment has been initiated
payment.processingThe payment is actively being settled
payment.settledFunds have settled on-chain
payment.deliveredFiat has been deposited into the recipient’s account
payment.failedThe payment could not be completed (includes failure_reason)
payment.cancelledThe payment was cancelled before processing
conversion.completedA currency conversion has finished
offramp.settledThe off-ramp bank transfer has been submitted
offramp.deliveredFiat delivery confirmed by the destination bank
offramp.failedThe off-ramp could not be completed (includes failure_reason)
compliance.review_requiredA transaction has been flagged for manual compliance review

Webhook payload structure

Every event RemitFlex sends has the same envelope structure:
{
  "id": "evt_01HX9P5S3KVZWP9QJDB6CTYMX",
  "type": "payment.delivered",
  "created_at": "2024-01-15T14:30:00Z",
  "data": {
    "payment_id": "pmt_01HX4N3RKVZWP9QJDB6CTYMX8",
    "status": "delivered",
    "amount": 500,
    "currency": "USDC",
    "destination_currency": "EUR",
    "converted_amount": 461.25,
    "delivered_at": "2024-01-15T14:28:00Z"
  }
}
FieldTypeDescription
idstringUnique event ID, prefixed evt_. Use this to deduplicate retried deliveries.
typestringThe event type string (e.g., payment.delivered)
created_atstringISO 8601 timestamp when the event was generated
dataobjectEvent-specific payload; structure varies by type

Verify webhook signatures

RemitFlex signs every webhook request with HMAC-SHA256 using your webhook secret. The signature is sent in the X-RemitFlex-Signature header:
X-RemitFlex-Signature: sha256=a3f9e2c1b8d047...
Always verify this signature before processing the payload. Skipping verification makes your endpoint vulnerable to spoofed requests.
const crypto = require('crypto');

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

// Express.js example
app.post('/webhooks/remitflex', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-remitflex-signature'];
  const isValid = verifyWebhook(req.body, signature, process.env.REMITFLEX_WEBHOOK_SECRET);

  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(req.body);
  // Handle event...
  res.status(200).send('OK');
});
Compute the HMAC over the raw request body bytes, not the parsed JSON object. Any whitespace or key-ordering difference in the serialized form will produce a different hash and cause verification to fail.
Use timingSafeEqual (JavaScript) or hmac.compare_digest (Python) for the final comparison rather than === or ==. Constant-time comparison prevents timing attacks that could allow an attacker to guess your secret.

Retry policy

If your endpoint returns a non-2xx HTTP status code or fails to respond within 10 seconds, RemitFlex considers the delivery failed and retries automatically:
AttemptDelay after previous failure
1st retry30 seconds
2nd retry5 minutes
3rd retry30 minutes
4th retry2 hours
5th retry8 hours
After five failed attempts, the event is marked as undeliverable and you will receive a dashboard alert. You can manually replay individual events from Dashboard → Settings → Webhooks → Event log.
Because retries mean the same event may arrive more than once, make your handler idempotent. Use the id field (e.g., evt_01HX9P5S...) to record which events you have already processed and skip duplicates.

Responding to webhooks

Your endpoint must return an HTTP 200 response to acknowledge receipt. RemitFlex treats any status outside the 2xx range as a failure and schedules a retry. Keep your response fast. If you need to perform slow operations (database writes, downstream API calls), acknowledge the webhook immediately and process the payload asynchronously:
app.post('/webhooks/remitflex', express.raw({ type: 'application/json' }), async (req, res) => {
  const signature = req.headers['x-remitflex-signature'];

  if (!verifyWebhook(req.body, signature, process.env.REMITFLEX_WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  // Acknowledge immediately — before any async work
  res.status(200).send('OK');

  // Process asynchronously
  const event = JSON.parse(req.body);
  await processEvent(event);
});