Webhook Setup

Send signed events to VertexY so the platform can build velocity, graph, and behavioural history.

What /events/ingest is for

POST /events/ingest is how you stream your event history into VertexY.

Use it for:

  • user creation and login activity
  • order lifecycle changes
  • payment success and failure
  • refunds, disputes, and chargebacks

Assessment answers the question: “Should I approve this transaction right now?”

Event ingestion answers the question: “What history and relationships should VertexY learn from over time?”

Authentication model

This endpoint does not use bearer auth.

Instead, every request must include:

  • x-event-signature
  • x-event-timestamp
  • x-event-nonce

The signature is:

plaintext
HMAC-SHA256(rawRequestBody, webhookSigningSecret)

Minimal event example

json
{
  "companyId": "a1b2c3d4-e5f6-4789-abcd-ef1234567890",
  "eventSource": "checkout-service",
  "externalEventId": "evt_100001",
  "idempotencyKey": "evt_100001",
  "userId": "user_123",
  "eventType": "payment_succeeded",
  "timestamp": "2026-04-07T12:00:00.000Z",
  "metadata": {
    "email": "buyer@example.com",
    "ipAddress": "203.0.113.10",
    "deviceId": "device_abc_001",
    "orderId": "order_100001"
  },
  "paymentDetails": {
    "methodType": "card",
    "gatewayPaymentId": "pay_100001",
    "fingerprint": "pm_hash_001",
    "amountMinor": 4999,
    "currency": "USD",
    "authStatus": "authorized"
  }
}

Working example with Node.js

javascript
import crypto from 'crypto';

const event = {
  companyId: process.env.VERTEXY_COMPANY_ID,
  eventSource: 'checkout-service',
  externalEventId: 'evt_100001',
  idempotencyKey: 'evt_100001',
  userId: 'user_123',
  eventType: 'payment_succeeded',
  timestamp: new Date().toISOString(),
  metadata: {
    email: 'buyer@example.com',
    ipAddress: '203.0.113.10',
    deviceId: 'device_abc_001',
    orderId: 'order_100001',
  },
  paymentDetails: {
    methodType: 'card',
    gatewayPaymentId: 'pay_100001',
    fingerprint: 'pm_hash_001',
    amountMinor: 4999,
    currency: 'USD',
    authStatus: 'authorized',
  },
};

const body = JSON.stringify(event);
const timestamp = String(Math.floor(Date.now() / 1000));
const nonce = crypto.randomUUID();
const signature = crypto
  .createHmac('sha256', process.env.VERTEXY_WEBHOOK_SECRET)
  .update(body)
  .digest('hex');

const res = await fetch('https://api.vertexY.com/api/events/ingest', {
  method: 'POST',
  headers: {
    'content-type': 'application/json',
    'x-event-signature': signature,
    'x-event-timestamp': timestamp,
    'x-event-nonce': nonce,
  },
  body,
});

const data = await res.json();

Response shape

json
{
  "id": "be0a9801-8d40-412e-a5df-5c70a3a42f55",
  "status": "accepted",
  "duplicate": false,
  "assessment": {
    "assessmentId": "c8acf6d5-8bf4-4b80-a7e5-1b33583c1c23",
    "riskScore": 31,
    "action": "review",
    "recommendedAction": "review",
    "policyMode": "hybrid",
    "riskLevel": "medium",
    "reasonCodes": [],
    "featureContributions": {},
    "engineVersion": "v2",
    "latencyMs": 43
  }
}

Idempotency and retries

idempotencyKey is required.

Use it to make retries safe:

  • first delivery creates the event
  • repeat delivery with the same key is treated as a duplicate
  • duplicates do not increment usage again

In rare races, a duplicate request may receive:

  • 503 Service Unavailable
  • code: ASSESSMENT_PENDING

That means the original event was accepted but its canonical assessment is still being finalized. Retry shortly.

Replay protection

The ingest pipeline rejects:

  • missing timestamp or nonce
  • stale timestamps outside the allowed replay window
  • repeated nonce values within the configured nonce TTL

Rate limiting

The public ingest route is rate limited. If you exceed the window you receive 429 Too Many Requests.

Recommended event strategy

Send all supported event types, not just successful payments.

At minimum, ingest:

  • user_created
  • login_event
  • order_created
  • payment_failed
  • payment_succeeded
  • dispute_opened
  • chargeback_received

Tips for higher-quality models

  • Keep userId stable across your systems.
  • Use gateway or provider event IDs as externalEventId when possible.
  • Use the same identity signals in both assess and ingest.
  • Include paymentDetails for payment events.
  • Include contextual fields like billingAddress, shippingAddress, deviceMeta, and ipGeo.

Related guides