Webhooks
Overview
Our Webhooks API lets your application receive real-time updates whenever customers, transactions, or counterparties change in Conduit. You can register an HTTPS endpoint, and Conduit will deliver event notifications to it automatically. This means your application stays updated without constant polling.
Getting started
We offer two ways to configure and manage webhooks on your account
- Via the conduit Dashboard
- Login into your Conduit Dashboard
- Click Webhooks in the navigation menu to view, create, or manage endpoints.
- Note: You need to have developer permissions to see this section on the dashboard. Reach out to your account manager for access if you don't.
- Via the Webhooks API
- Use our Webhooks API to programmatically create, update, list, or delete webhook endpoints.
- See the API Reference for request and response examples.
- This document will show you can get started using the API
Tip
Your webhook endpoint must accept JSON payloads and respond with a
200 OK
status quickly to prevent retries and timeouts. Conduit will retry delivery up to 10 times over 24 hours before marking the event as failed.
Authentication
All API requests require authentication using your API Key sent in the Authorization header. You can generate and manage your API keys anytime in the Conduit Dashboard under API Keys.
curl -X POST https://api.conduit.financial/[END_POINT] \
-H "X-API-Key: your_api_key" \
-H "X-API-Secret: your_api_secret" \
-H "Content-Type: application/json"
Registering Webhook Endpoint
To start receiving real-time updates, you must register your webhook endpoint with Conduit. You can do this by sending a POST request to the /webhooks API endpoint with your webhook details.
Example Request:
curl -X POST https://api.conduit.financial/webhooks \
-H "X-API-Key: your_api_key" \
-H "X-API-Secret: your_api_secret" \
-H "Content-Type: application/json" \
-d '{
"url": "your_webhook_url",
"status": "enabled",
"events": ["your_subscribed_event"],
"organizationId": "your_client_id"
}'
Request Parameters:
Parameter | Type | Description |
---|---|---|
url | string | Your webhook endpoint URL to receive events |
status | string | Status of the webhook, typically "enabled" when creating |
events | Array | Array of event types you want to subscribe to ( refer to events section on the supported events) |
organizationId | string | Your client or organization identifier |
Example Response
{
"id": "whk_31BbTJ0ORWosbmona9WP0ThJYT5",
"url": "https://www.example.com/webhooks",
"status": "enabled",
"organizationId": "client_2zsj24vsMLU9emYzu2rZXlJhQs",
"events": [
"counterparty.active"
]
}
Response Field description
Field | Description | |
---|---|---|
id | The unique identifier of the webhook entry | |
url | Your webhook endpoint URL to receive events | |
events | Array of event types you subscribed to ( refer to events | |
organizationId | Your client or organization identifier | |
status | Status of the webhook, "enabled" |
Retrieve Your Webhook Secret
Before you can verify incoming webhook requests, you need the secret associated with your webhook. This secret is used to validate the authenticity of each request from Conduit, protecting your system from unauthorized or forged events.
To find your webhook secret:
- Log into your Conduit Dashboard
- Navigate to the Webhooks tab.
- Locate the webhook you created and click on it
- Click on it to view the Key Secret field this what you use in your signature verification process.
Verifying Webhook Requests
For security, every webhook request from Conduit must be verified before processing. Use the secret you retrieved above to validate the HMAC SHA-256 signature included in each request header.
Below is an example Node.js Express webhook endpoint that performs:
• Extraction of signature headers
• HMAC signature verification using the secret
• Replay attack prevention via timestamp validation
• Constant-time comparison to prevent timing attacks
const express = require('express');
const crypto = require('crypto');
const app = express();
// Middleware to parse JSON bodies
app.use(express.json());
// Middleware to validate incoming webhook requests
const validateWebhook = (req, res, next) => {
// Extract signature and timestamp headers from the request
const signature = req.headers['conduit-signature'];
const timestamp = req.headers['conduit-signature-timestamp'];
// Reject request if headers are missing
if (!signature || !timestamp) {
console.error('Missing signature headers');
return res.status(401).send({ error: 'Missing signature headers' });
}
// Get your webhook secret from environment variables
const secret = process.env.WEBHOOK_SECRET;
if (!secret) {
console.error('Webhook secret is not configured');
return res.status(500).send({ error: 'Server configuration error' });
}
// Convert request body to string for signing
const payload = JSON.stringify(req.body);
// Create the string to sign: "<timestamp>.<payload>"
const stringToSign = `${timestamp}.${payload}`;
try {
// Compute HMAC SHA256 hash using your secret
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(stringToSign)
.digest('hex');
// Compare expected signature with the one sent by Conduit
if (expectedSignature !== signature) {
console.error('Invalid signature');
return res.status(401).send({ error: 'Invalid signature' });
}
// Signature verified — proceed to next middleware or route handler
next();
} catch (error) {
console.error('Webhook validation error:', error);
return res.status(401).send({ error: 'Webhook validation failed' });
}
};
// Webhook endpoint with validation middleware applied
app.post('/', validateWebhook, (req, res) => {
res.status(200).send({ message: 'Webhook received' });
});
// Start server
const PORT = process.env.PORT || 9876;
app.listen(PORT, () => {
console.log(`Webhook client listening on port ${PORT}`);
});
Structure of Webhook Payload
Each webhook you receive from Conduit follows a consistent structure.
{
"event": "WebhookEventType",
"version": "1.0",
"data": {
// object with the data
}
}
}
Field descriptions:
Field | Type | Description |
---|---|---|
event | string | The type of event that occurred, e.g., counterparty.active, customer.created. |
version | string | The webhook payload version. Use this to ensure compatibility with future updates. |
data | object | Contains the main event data, this can counterparty, transaction or customer. |
The follow are the examples of the payloads that you will receive based for each resource type we currently support.
Counterparty Event
This is response you will get when counterparty is compliance review
{
"event": "counterparty.in_compliance_review",
"version": "1.0",
"data": {
"counterparty": {
"id": "cp_31C7TAhHBpmrTYNXnzn6lrzlzqY",
"type": "business",
"businessName": "Test",
"website": "https://www.counterparty.com",
"address": {
"streetLine1": "Flat 1 , 4th Street, Ibex Hill ",
"streetLine2": "Lusaka",
"city": "Kitwe",
"state": "Lusaka",
"postalCode": "10101",
"country": "ALB"
},
"paymentMethods": [
{
"id": "bank_31C7TCE61yBrxPFELkdrwcD56hX",
"type": "bank",
"rail": [
"swift"
],
"bankName": "FNB",
"accountType": "checking",
"accountOwnerName": "Test",
"accountNumber": "4658579489498",
"routingNumber": "",
"swiftCode": "EMPOALTR",
"currency": "USD",
"address": {
"streetLine1": "Albanian Alps",
"city": "Tirana",
"state": "Shkodër County",
"postalCode": "101010",
"country": "ALB"
}
}
],
"documents": [
{
"documentId": "doc_31C7T3kpDDL0B3xXB8H2WZwq9ZH",
"documentPurpose": "transaction_justification",
"documentType": "contract",
"documentName": "Customer KYB.pdf",
"uploadedAt": "2025-08-12T16:30:05.044Z"
}
],
"status": "in_compliance_review",
"createdAt": "2025-08-12T16:30:05.725Z",
"updatedAt": "2025-08-12T16:30:05.725Z",
"clientId": "client_31C4ON5QZPrSnpGcUTDzQAPVXGS"
}
}
}
Customer Event
This an example event when a customer is created
{
"event": "customer.created",
"version": "1.0",
"data": {
"customer": {
"id": "cus_31C4ghJdDTNf3OdeMmb98q4868JU4",
"type": "business",
"businessLegalName": "Testing",
"businessTradeName": null,
"industry": null,
"email": null,
"phone": null,
"website": null,
"registeredDate": null,
"registeredAddress": null,
"operatingAddress": null,
"kybLink": "https://verify-sandbox.aiprise.com/?business_onboarding_session_id=dc004638-4258-4676-8b28-c6901896aafeca3",
"kybLinkExpiration": "2025-11-10T16:07:12.841Z",
"kybLinkGeneratedAt": "2025-08-12T16:07:12.841Z",
"kybCompletedAt": null,
"status": "created",
"organizationId": "31C4ON5QZPrSn89pGcUTDzQAPVXGS",
"tags": null,
"kybData": null,
"industryData": null,
"taxIdentificationNumber": null,
"businessEntityId": null,
"isSubsidiary": false,
"kybSetupBy": "client",
"createdAt": "2025-08-12T16:07:12.370Z",
"updatedAt": "2025-08-12T16:07:12.370Z",
"deletedAt": null,
"isFinancialInstitution": null,
"identifications": [],
"documents": []
}
}
}
Transaction Event
This an example of a transaction event for a successful deposit
{
"event": "transaction.completed",
"version": "1.0",
"data": {
"transaction": {
"type": "deposit",
"id": "trxn_31C6aorcaHHEl1jLbSzXRTbj7eC",
"status": "COMPLETED",
"source": {
"address": "0x0000000000000000000000000000000000000000",
"amount": {
"assetType": "USDC",
"decimals": 6,
"standardDecimals": 6,
"amount": "10000000000",
"assetTypeNetwork": {
"assetType": "USDC",
"networkId": "ethereum:goerli"
}
}
},
"destination": {
"id": "acct_31C4OLZH4qdXXXizursw2FsDcmb",
"amount": {
"assetType": "USDC",
"decimals": 6,
"standardDecimals": 6,
"amount": "10000000000",
"assetTypeNetwork": {
"assetType": "USDC",
"networkId": "ethereum:goerli"
}
}
},
"purpose": null,
"reference": null,
"createdAt": "2025-08-12T16:22:53.782Z",
"completedAt": "2025-08-12T16:23:03.007Z",
"clientId": "client_31C4ON5QZPrSnpGcUTDzQAPVXGS"
}
}
}
Managing Webhooks
Once your webhook endpoint is verified and running, you can manage your webhook subscriptions via the API.
Update Webhook
curl -X PUT https://api.conduit.financial/webhooks/whk_2ji0un2T6BaGhHKsmJu93Zf5OQm \
-H "X-API-Key: your_api_key" \
-H "X-API-Secret: your_api_secret" \
-H "Content-Type: application/json" \
-d '{
"url": "your_new_webhook_url",
"status": "disabled",
"events": ["your_new_subscribed_event"]
}'
Delete Webhook
curl -X DELETE https://api.conduit.financial/webhooks/whk_2ji0un2T6BaGhHKsmJu93Zf5OQm \
--H "X-API-Key: your_api_key" \
--H "X-API-Secret: your_api_secret" \
--H "Content-Type: application/json"
Get Webhook
curl -X GET https://api.conduit.financial/webhooks/whk_2ji0un2T6BaGhHKsmJu93Zf5OQm \
-H "X-API-Key: your_api_key" \
-H "X-API-Secret: your_api_secret" \
-H "Content-Type: application/json"
List Webhooks
curl -X GET https://api.conduit.financial/webhooks \
-H "X-API-Key: your_api_key" \
-H "X-API-Secret: your_api_secret" \
-H "Content-Type: application/json"
Supported Webhook Events
Conduit supports the following webhook event notifications, grouped by resource type.
Counterparty Events
These events notify you of changes in a counterparty’s lifecycle from activation to compliance checks.
Event Name | Description |
---|---|
counterparty.active | Counterparty becomes active |
counterparty.compliance_rejected | Counterparty fails compliance review |
counterparty.deleted | Counterparty is deleted |
counterparty.in_compliance_review | Counterparty enters compliance review |
Customer Events
These events track important customer status updates — including onboarding progress, compliance checks, and KYB status.
Event Name | Description |
---|---|
customer.active | Customer becomes active |
customer.in_compliance_review | Customer enters compliance review |
customer.compliance_rejected | Customer fails compliance review |
customer.created | Customer is created |
customer.kyb_in_progress | Customer KYB verification in progress |
customer.kyb_expired | Customer KYB verification expired |
customer.kyb_missing_information | Customer KYB verification missing information |
customer.account_onboarding_pending | Customer onboarding pending |
Transaction Events
These events cover the full transaction lifecycle — from creation to settlement — including compliance decisions and payment processing.
Event Name | Description |
---|---|
transaction.created | New transaction |
transaction.compliance_approved | Transaction approved in compliance |
transaction.compliance_rejected | Transaction rejected in compliance |
transaction.completed | Transaction completed |
transaction.awaiting_funds | Transaction awaiting funds |
transaction.funds_received | Transaction funds received |
transaction.cancelled | Transaction cancelled |
transaction.in_compliance_review | Transaction under compliance review |
transaction.awaiting_compliance_review | Transaction awaiting compliance review |
transaction.processing_withdrawal | Processing a withdrawal |
transaction.withdrawal_processed | Withdrawal processed |
transaction.processing_settlement | Processing settlement |
transaction.settlement_processed | Settlement processed |
transaction.processing_payment | Processing payment |
transaction.payment_processed | Payment processed |
Best Practices
The following are the list of best practices that you need to have in place to for a smooth integration with our webhook.
1. Handle Idempotency with conduit-webhook-idempotency-key
conduit-webhook-idempotency-key
Every webhook request from Conduit includes a unique conduit-webhook-idempotency-key
header.
Use this key to ensure that the same event is not processed more than once.
Recommended approach:
- Read the header value from the request.
- Check if this key was already processed in your system.
- Skip processing if the key is found (to prevent duplicate effects).
- Store keys temporarily in a database or cache (e.g., Redis)
- Clean up old keys periodically.
Why it’s important:
Webhook retries can occur due to network issues or failed acknowledgements.
Idempotency ensures that your system processes each event only once, preserving data integrity.
2. Verify Webhook Signatures
Always validate webhook signatures to confirm the request came from Conduit and has not been tampered with.
3. Respond Quickly
Return a 200 OK
status as soon as possible. If processing takes a long time, consider deferring it to a background job.
IP Address Whitelisting
For an additional layer of security, you can restrict incoming webhook requests to only those originating from Conduit’s official IP addresses.
This ensures that only Conduit can trigger your webhook endpoint, reducing the risk of unauthorized requests.
Why Whitelist IPs?
• Prevents webhook spoofing from unknown sources.
• Adds an extra security layer alongside signature verification.
• Useful for organizations with strict network access controls.
Environment | IP Address |
---|---|
Sandbox | 3.97.46.187/32 |
Live | 3.98.205.40/32 |
For more on the Webhooks API information please check the API References Section
Updated about 13 hours ago