Webhook Configuration
Webhooks allow your application to receive real-time HTTP POST notifications when events occur in your ONE project -- transactions confirmed, trades executed, payments completed, and more. You can configure webhooks through the dashboard or programmatically with the OneEngineClient.
Client Setup
import { OneEngineClient } from '@one_deploy/sdk';
const engine = new OneEngineClient({
baseUrl: process.env.ONE_ENGINE_URL!,
clientId: process.env.ONE_CLIENT_ID!,
secretKey: process.env.ONE_SECRET_KEY!,
});
Methods
| Method | Description |
|---|---|
createWebhook(input) | Create a new webhook subscription. |
getWebhooks(projectId) | List all webhooks for a project. |
getWebhook(webhookId) | Get a single webhook by ID. |
updateWebhook(webhookId, updates) | Update an existing webhook. |
deleteWebhook(webhookId) | Delete a webhook subscription. |
testWebhook(webhookId) | Send a test event to the webhook endpoint. |
getWebhookDeliveries(webhookId, options?) | Retrieve delivery logs for a webhook. |
WebhookEventType
The WebhookEventType enum defines all events you can subscribe to.
enum WebhookEventType {
// Transaction events
TRANSACTION_CONFIRMED = 'transaction.confirmed',
TRANSACTION_FAILED = 'transaction.failed',
TRANSACTION_PENDING = 'transaction.pending',
// Wallet events
WALLET_CREATED = 'wallet.created',
WALLET_BALANCE_CHANGE = 'wallet.balance_change',
// Payment events
ONRAMP_COMPLETED = 'onramp.completed',
ONRAMP_FAILED = 'onramp.failed',
OFFRAMP_COMPLETED = 'offramp.completed',
OFFRAMP_FAILED = 'offramp.failed',
SWAP_COMPLETED = 'swap.completed',
SWAP_FAILED = 'swap.failed',
// AI Trading events
TRADE_OPENED = 'trade.opened',
TRADE_CLOSED = 'trade.closed',
TRADE_PROFIT_TAKEN = 'trade.profit_taken',
TRADE_STOP_LOSS = 'trade.stop_loss',
STRATEGY_ACTIVATED = 'strategy.activated',
STRATEGY_PAUSED = 'strategy.paused',
// Forex events
FOREX_POSITION_OPENED = 'forex.position_opened',
FOREX_POSITION_CLOSED = 'forex.position_closed',
FOREX_POOL_UPDATED = 'forex.pool_updated',
// Contract events
CONTRACT_DEPLOYED = 'contract.deployed',
CONTRACT_EVENT = 'contract.event',
// Project events
PROJECT_QUOTA_WARNING = 'project.quota_warning',
PROJECT_QUOTA_REACHED = 'project.quota_reached',
}
Creating a Webhook
CreateWebhookInput
interface CreateWebhookInput {
projectId: string;
url: string; // HTTPS endpoint that receives POST requests
events: WebhookEventType[]; // Events to subscribe to
description?: string; // Human-readable label
secret?: string; // Shared secret for HMAC signature verification
active?: boolean; // Defaults to true
headers?: Record<string, string>; // Custom headers sent with every delivery
}
Basic Setup
const res = await engine.createWebhook({
projectId: 'proj_abc123',
url: 'https://api.myapp.com/webhooks/one',
events: [
WebhookEventType.TRANSACTION_CONFIRMED,
WebhookEventType.SWAP_COMPLETED,
WebhookEventType.TRADE_CLOSED,
],
description: 'Production transaction notifications',
secret: 'whsec_my_signing_secret',
});
if (res.success) {
console.log('Webhook ID:', res.data.id);
console.log('URL:', res.data.url);
console.log('Events:', res.data.events);
}
Webhook Response Type
interface Webhook {
id: string;
projectId: string;
url: string;
events: WebhookEventType[];
description?: string;
secret: string;
active: boolean;
headers?: Record<string, string>;
createdAt: string; // ISO-8601
updatedAt: string; // ISO-8601
}
Listing Webhooks
const res = await engine.getWebhooks('proj_abc123');
if (res.success) {
for (const webhook of res.data) {
console.log(`[${webhook.id}] ${webhook.url} -- ${webhook.active ? 'active' : 'paused'}`);
console.log(' Events:', webhook.events.join(', '));
}
}
Updating a Webhook
Pass only the fields you want to change. Omitted fields keep their current value.
const res = await engine.updateWebhook('whk_abc123', {
events: [
WebhookEventType.TRADE_OPENED,
WebhookEventType.TRADE_CLOSED,
WebhookEventType.TRADE_STOP_LOSS,
],
active: true,
});
if (res.success) {
console.log('Updated events:', res.data.events);
}
Testing a Webhook
Send a synthetic test event to your endpoint to verify connectivity and payload handling.
const res = await engine.testWebhook('whk_abc123');
if (res.success) {
console.log('Test delivery ID:', res.data.deliveryId);
console.log('Status code:', res.data.statusCode);
console.log('Response time:', res.data.durationMs, 'ms');
if (res.data.statusCode === 200) {
console.log('Webhook endpoint is responding correctly.');
} else {
console.warn('Endpoint returned non-200 status.');
}
}
The test event payload looks like this:
{
"id": "evt_test_123",
"type": "webhook.test",
"projectId": "proj_abc123",
"timestamp": "2025-01-15T12:00:00Z",
"data": {
"message": "This is a test webhook delivery."
}
}
Webhook Delivery Logs
Track delivery attempts, response codes, and retry status for each webhook.
getWebhookDeliveries
interface GetWebhookDeliveriesOptions {
page?: number; // 1-based (default: 1)
limit?: number; // Items per page (default: 20, max: 100)
status?: 'success' | 'failed' | 'pending';
}
interface WebhookDelivery {
id: string;
webhookId: string;
eventType: WebhookEventType;
url: string;
statusCode: number | null; // null if the request failed to connect
requestBody: string; // JSON payload sent
responseBody?: string; // Response from your endpoint
durationMs: number;
attempt: number; // 1 = first attempt, 2+ = retries
maxAttempts: number;
status: 'success' | 'failed' | 'pending';
createdAt: string; // ISO-8601
nextRetryAt?: string; // ISO-8601, present if status is 'pending'
}
Querying Deliveries
const res = await engine.getWebhookDeliveries('whk_abc123', {
page: 1,
limit: 25,
status: 'failed',
});
if (res.success) {
for (const delivery of res.data) {
console.log(
`[${delivery.id}] ${delivery.eventType} -- ` +
`${delivery.status} (attempt ${delivery.attempt}/${delivery.maxAttempts})`
);
if (delivery.statusCode) {
console.log(` Status: ${delivery.statusCode}`);
}
if (delivery.nextRetryAt) {
console.log(` Next retry: ${delivery.nextRetryAt}`);
}
}
}
Retry Behaviour
When a webhook delivery fails (non-2xx response or connection error), the ONE Engine retries with exponential backoff:
| Attempt | Delay after failure |
|---|---|
| 1st retry | 30 seconds |
| 2nd retry | 2 minutes |
| 3rd retry | 15 minutes |
| 4th retry | 1 hour |
| 5th retry | 4 hours |
After 5 failed retry attempts (6 total attempts including the original), the delivery is marked as permanently failed. You can inspect failed deliveries in the dashboard or via getWebhookDeliveries.
If a webhook endpoint fails consistently for 24 hours, the webhook is automatically paused to prevent unnecessary load. Re-enable it from the dashboard or by calling updateWebhook(webhookId, { active: true }) after fixing the endpoint.
Verifying Webhook Signatures
Every delivery includes an X-One-Signature header containing an HMAC-SHA256 signature of the request body, signed with your webhook secret. Always verify this signature to ensure the payload was sent by the ONE Engine.
import crypto from 'crypto';
function verifyWebhookSignature(
body: string,
signature: string,
secret: string
): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(body, 'utf8')
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// Express example
app.post('/webhooks/one', (req, res) => {
const signature = req.headers['x-one-signature'] as string;
const body = JSON.stringify(req.body);
if (!verifyWebhookSignature(body, signature, process.env.WEBHOOK_SECRET!)) {
return res.status(401).send('Invalid signature');
}
const event = req.body;
console.log('Received event:', event.type);
console.log('Data:', event.data);
// Process the event...
res.status(200).send('OK');
});
Complete Webhook Setup Flow
The following example demonstrates the full lifecycle: create a webhook, test it, verify deliveries, and clean up.
import { OneEngineClient, WebhookEventType } from '@one_deploy/sdk';
const engine = new OneEngineClient({
baseUrl: process.env.ONE_ENGINE_URL!,
clientId: process.env.ONE_CLIENT_ID!,
secretKey: process.env.ONE_SECRET_KEY!,
});
async function setupWebhooks() {
// 1. Create a webhook
const createRes = await engine.createWebhook({
projectId: 'proj_abc123',
url: 'https://api.myapp.com/webhooks/one',
events: [
WebhookEventType.TRANSACTION_CONFIRMED,
WebhookEventType.TRANSACTION_FAILED,
WebhookEventType.SWAP_COMPLETED,
WebhookEventType.TRADE_OPENED,
WebhookEventType.TRADE_CLOSED,
WebhookEventType.FOREX_POSITION_OPENED,
WebhookEventType.FOREX_POSITION_CLOSED,
WebhookEventType.PROJECT_QUOTA_WARNING,
],
description: 'Main production webhook',
secret: 'whsec_production_secret_value',
});
if (!createRes.success) {
console.error('Failed to create webhook:', createRes.error);
return;
}
const webhookId = createRes.data.id;
console.log('Created webhook:', webhookId);
// 2. Test the endpoint
const testRes = await engine.testWebhook(webhookId);
if (testRes.success && testRes.data.statusCode === 200) {
console.log('Test delivery successful.');
} else {
console.warn('Test delivery issue. Check your endpoint.');
}
// 3. Check delivery logs
const deliveries = await engine.getWebhookDeliveries(webhookId, { limit: 5 });
if (deliveries.success) {
console.log(`Recent deliveries: ${deliveries.data.length}`);
for (const d of deliveries.data) {
console.log(` ${d.eventType} -- ${d.status} (${d.statusCode})`);
}
}
// 4. List all webhooks for the project
const allWebhooks = await engine.getWebhooks('proj_abc123');
if (allWebhooks.success) {
console.log(`Total webhooks: ${allWebhooks.data.length}`);
}
}
setupWebhooks();
Next Steps
- Team Management -- control who can manage webhooks.
- Usage & Analytics -- track webhook delivery volume.
- API Keys -- secure the credentials used for webhook verification.