Event Ingestion
Send signed account, order, payment, refund, dispute, and chargeback events to improve future decisions.
VertexY event ingestion turns isolated real-time decisions into a history-aware fraud graph. Send events from trusted backend services only.
/events/ingestSigned event ingestion
Uses HMAC SHA-256 headers instead of bearer tokens. VertexY verifies the exact raw request body.
Supported event types
| Category | Event types |
| --- | --- |
| Account | user_created, login_event |
| Order | order_created, order_canceled |
| Payment | payment_failed, payment_succeeded, payment_captured |
| Refund | refund_requested, refund_completed |
| Dispute | dispute_opened, chargeback_received |
Required fields
| Field | Description |
| --- | --- |
| companyId | Your VertexY company UUID. |
| eventSource | Internal service sending the event, such as checkout-service. |
| externalEventId | Event ID from your own system. |
| idempotencyKey | Stable retry-safe key for this event. |
| userId | Stable customer/user ID from your system. |
| eventType | One of the supported event types. |
| timestamp | ISO 8601 event time. |
| metadata | Business context such as order ID, channel, or failure reason. |
Optional enrichment fields include paymentDetails, billingAddress, shippingAddress, cardDetails, deviceMeta, and ipGeo.
Signing request bodies
import crypto from "crypto";
async function sendVertexYEvent(payload) {
const rawBody = JSON.stringify(payload);
const signature = crypto
.createHmac("sha256", process.env.VERTEXY_WEBHOOK_SECRET)
.update(rawBody)
.digest("hex");
const response = await fetch(`${process.env.VERTEXY_API_BASE_URL}/events/ingest`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-event-signature": signature,
"x-event-timestamp": String(Math.floor(Date.now() / 1000)),
"x-event-nonce": crypto.randomUUID(),
},
body: rawBody,
});
if (!response.ok) {
throw new Error(`VertexY event ingest failed with ${response.status}`);
}
return response.json();
}Example events
US payment succeeded
{
"companyId": "a1b2c3d4-e5f6-4789-abcd-ef1234567890",
"eventSource": "checkout-service",
"externalEventId": "evt_us_payment_10492",
"idempotencyKey": "evt_us_payment_10492",
"userId": "usr_8f7b2c9a4d",
"eventType": "payment_succeeded",
"timestamp": "2026-05-18T10:30:00.000Z",
"metadata": {
"orderId": "ord_us_10492",
"channel": "web"
},
"paymentDetails": {
"methodType": "card",
"provider": "stripe",
"fingerprint": "pmh_visa_44e9",
"amountMinor": 12999,
"currency": "USD",
"authStatus": "authorized",
"threeDsResult": "not_attempted"
},
"billingAddress": {
"country": "US",
"postalCode": "10001",
"city": "New York"
}
}Europe challenged payment
{
"companyId": "a1b2c3d4-e5f6-4789-abcd-ef1234567890",
"eventSource": "payments-service",
"externalEventId": "evt_eu_auth_66210",
"idempotencyKey": "evt_eu_auth_66210",
"userId": "usr_eu_7b2aa91",
"eventType": "payment_failed",
"timestamp": "2026-05-18T12:05:00.000Z",
"metadata": {
"orderId": "ord_eu_66210",
"market": "de"
},
"paymentDetails": {
"methodType": "card",
"provider": "adyen",
"fingerprint": "pmh_mastercard_8cd2",
"amountMinor": 8890,
"currency": "EUR",
"authStatus": "failed",
"failureCategory": "authentication_failed",
"threeDsResult": "failed"
},
"deviceMeta": {
"browser": "Chrome",
"language": "de-DE",
"timezone": "Europe/Berlin"
}
}Southeast Asia wallet order
{
"companyId": "a1b2c3d4-e5f6-4789-abcd-ef1234567890",
"eventSource": "mobile-checkout",
"externalEventId": "evt_sg_wallet_77812",
"idempotencyKey": "evt_sg_wallet_77812",
"userId": "usr_sea_2190ab",
"eventType": "order_created",
"timestamp": "2026-05-18T14:15:00.000Z",
"metadata": {
"orderId": "ord_sg_77812",
"channel": "mobile_app",
"voucherCode": "MAYSALE"
},
"paymentDetails": {
"methodType": "wallet",
"provider": "grabpay",
"walletId": "wallet_hash_81cd",
"amountMinor": 8490,
"currency": "SGD",
"authStatus": "pending"
},
"deviceMeta": {
"os": "Android",
"language": "en-SG",
"timezone": "Asia/Singapore"
}
}Retry behavior
- Reuse the same
idempotencyKeywhen retrying the same event. - Generate a new
x-event-noncefor each HTTP attempt. - Keep timestamps close to the send time so replay protection can validate the request.
- Treat
2xxas accepted and retry5xxwith backoff.