Event Schema
Every event delivered by XRNotify follows a canonical top-level structure. The event-type-specific data lives inside the payload field.
Overview
Regardless of whether the event is a payment, NFT mint, DEX trade, or any other activity, the outer envelope is identical. This makes it straightforward to write a single parsing layer and then branch on event_type to reach type-specific payload handling.
Events are delivered as HTTP POST requests with a Content-Type: application/json header and a signed body. Always verify the X-XRNotify-Signature header before trusting the payload.
TypeScript interface
interface XRNotifyEvent<T = Record<string, unknown>> {
/** Unique event identifier in format xrpl:<ledger>:<txhash>:<type>[:<idx>] */
event_id: string;
/** Event type string (e.g. "payment.xrp", "nft.minted") */
event_type: EventType;
/** XRPL ledger index this event occurred in */
ledger_index: number;
/** ISO 8601 timestamp of ledger close */
timestamp: string;
/** Network: "mainnet" | "testnet" | "devnet" */
network: string;
/** The webhook that triggered this delivery */
webhook_id: string;
/** Event-type-specific payload */
payload: T;
}Field descriptions
| Field | Type | Description |
|---|---|---|
event_id | string | Globally unique, deterministic ID. Format: xrpl:<ledger>:<txhash>:<type>[:<idx>] |
event_type | string | One of the 23 supported event types (see EventType union below) |
ledger_index | number | XRPL ledger sequence number in which the transaction was validated |
timestamp | string | ISO 8601 datetime, always UTC, matching the ledger close time |
network | string | Always "mainnet" for production. "testnet" or "devnet" for test webhooks |
webhook_id | string | wh_ prefixed ID of the webhook that triggered this delivery |
payload | object | Event-type-specific fields. Schema varies by event_type |
The event_id format
Event IDs are deterministically generated from on-chain data, so the same ledger event always produces the same event_id. This makes them safe to use as idempotency keys in your processing layer.
# Pattern: xrpl:<ledger_index>:<tx_hash>:<event_type>[:<sub_index>] # Examples: xrpl:84512701:A1B2C3D4E5F6...1234:payment.xrp xrpl:84512705:F6E5D4C3B2A1...5678:nft.offer_accepted xrpl:84512710:123456789ABC...ABCD:dex.offer_partial:0 xrpl:84512710:123456789ABC...ABCD:dex.offer_partial:1
The optional :sub_index suffix appears when a single transaction generates multiple events of the same type (e.g., a single DEX trade filling multiple offers). Each resulting event gets a unique numeric index.
EventType union (all 23 values)
type EventType = // Payments | 'payment.xrp' | 'payment.issued' // NFTs | 'nft.minted' | 'nft.burned' | 'nft.offer_created' | 'nft.offer_accepted' | 'nft.offer_cancelled' // DEX | 'dex.offer_created' | 'dex.offer_cancelled' | 'dex.offer_filled' | 'dex.offer_partial' // Trustlines | 'trustline.created' | 'trustline.modified' | 'trustline.deleted' // Accounts | 'account.created' | 'account.deleted' | 'account.settings_changed' // Escrows | 'escrow.created' | 'escrow.finished' | 'escrow.cancelled' // Checks | 'check.created' | 'check.cashed' | 'check.cancelled';
Sample event (payment.xrp)
{
"event_id": "xrpl:84512701:A1B2C3D4E5F67890ABCDEF1234567890ABCDEF1234567890ABCDEF12345678:payment.xrp",
"event_type": "payment.xrp",
"ledger_index": 84512701,
"timestamp": "2024-01-15T14:23:07Z",
"network": "mainnet",
"webhook_id": "wh_abc123def456",
"payload": {
"sender": "rN7n3473SaZBCG4dFL75SqSGPpvNRRBXtK",
"receiver": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
"amount": "25000000",
"destination_tag": 1042,
"tx_hash": "A1B2C3D4E5F67890ABCDEF1234567890ABCDEF1234567890ABCDEF12345678"
}
}JSON Schema (top-level envelope)
Use this schema to validate inbound webhook bodies with any JSON Schema v2020-12 compatible validator (e.g., ajv in Node.js).
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://xrnotify.io/schemas/event.json",
"type": "object",
"required": [
"event_id",
"event_type",
"ledger_index",
"timestamp",
"network",
"webhook_id",
"payload"
],
"properties": {
"event_id": {
"type": "string",
"pattern": "^xrpl:\\d+:[A-F0-9]+:[a-z.]+(?::\\d+)?$"
},
"event_type": {
"type": "string"
},
"ledger_index": {
"type": "integer",
"minimum": 1
},
"timestamp": {
"type": "string",
"format": "date-time"
},
"network": {
"type": "string",
"enum": ["mainnet", "testnet", "devnet"]
},
"webhook_id": {
"type": "string",
"pattern": "^wh_"
},
"payload": {
"type": "object"
}
},
"additionalProperties": false
}Delivery HTTP headers
Every webhook POST includes the following headers alongside the event body:
| Header | Description |
|---|---|
X-XRNotify-Signature | HMAC-SHA256 signature of the raw request body. Format: sha256=<hex> |
X-XRNotify-Delivery-Id | Unique delivery attempt ID (dlv_ prefixed). Use for idempotency. |
X-XRNotify-Event-Id | The event_id from the body, repeated as a header for quick access |
X-XRNotify-Event-Type | The event_type from the body, repeated as a header |
X-XRNotify-Timestamp | Unix timestamp of when this delivery was dispatched |
Content-Type | Always application/json |