Events

The Versa protocol supports several primary event types — receipts, bookings, invoices, and itineraries — all sharing the same underlying schema. Beyond these, additional secondary event types can be registered by the same mechanism for real-time updates and status changes.

Register a specific type of event and filter receivers by the specific transaction data you are prepared to send. This allows senders to target only receivers that are interested in specific event types (receipts, itineraries, etc.) and are prepared to handle the corresponding data payload. This is an advanced usecase and your account must be opted in to enable this feature. Contact support@versa.org if interested.

Overview

The transaction event filtering feature allows you to specify which type of event data you will send when registering a receipt with the Versa Registry. This ensures that only receivers configured to handle your specific event type will receive the webhook delivery, which is recommended best practice.

Event Types

Currently supported event types:

Primary event types — all use the Versa schema:

  • receipt - A completed transaction with payment. The most common event type.
  • booking - A pre-purchase reservation; payment not required. Valid for travel itemization types only (car_rental, flight, lodging, transit_route).
  • invoice - An outstanding bill where payment is still due (header.paid < header.total).
  • itinerary - Travel information without financial data. See the Itinerary Schema.

Secondary (update) event types — reference an existing transaction:

  • transit_route.status.updated - Updates to the status of a transit route
  • transit_route.location.updated - Updates to the location of a transit route

API Usage

Receipt Registration with Event Specification

Include the event_type parameter in your receipt registration request to filter receivers by event type:

curl -X POST https://registry.versa.org/register \
  -H 'Authorization: Basic CLIENT_ID:CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "event_type": "receipt",
    "schema_version": "2.3.0",
    "handles": {
      "customer_email_domain": "acme.co"
    }
  }'

Request Parameters

FieldTypeDescription
event_typestringOptional. Filter receivers by transaction event type. Valid values: "receipt", "booking", "invoice", "itinerary"

When event_type is provided, only receivers that have registered to handle the specified event type will be included in the response. If the event_type parameter is not specified, it is assumed that a fully qualified receipt is available according to the Versa schema, and all receivers will be included regardless of their event type configuration.

Example Response

{
  "mode": "prod",
  "receipt_id": "rcpt_abc123def456",
  "transaction_id": "txn_789xyz012",
  "receivers": [
    {
      "org_id": "org_expense_tracker",
      "endpoint_url": "https://api.expensetracker.com/webhooks/versa",
      "secret": "whsec_abc123...",
      "event_type": "receipt"
    }
  ],
  "encryption_key": "pk_live_abc123..."
}

Note that receivers in the response will only include those configured to handle the specified event_type type.

Advanced Use-Cases

Beyond receipts, events can be leveraged to send additional or alternative representations of the data.

Bookings

When a reservation is confirmed but payment has not yet been collected (e.g., a hotel hold), send a booking event. Bookings are valid for travel itemization types only: car_rental, flight, lodging, or transit_route.

{
  "event_type": "booking",
  "schema_version": "2.3.0",
  "handles": {
    "customer_email": "traveler@company.com"
  }
}

Invoices

When payment is outstanding — e.g., a net-30 bill — send an invoice event. The schema is identical to a receipt, but header.paid will be less than header.total.

{
  "event_type": "invoice",
  "schema_version": "2.3.0",
  "handles": {
    "customer_email": "client@company.com"
  }
}

Itineraries

When sending travel confirmations without payment details attached, you can register an itinerary event. See the Itinerary Schema for the reduced field set.

{
  "event_type": "itinerary",
  "schema_version": "2.3.0",
  "handles": {
    "customer_email": "traveler@company.com",
    "merchant_group_code": "ABC789Z1"
  }
}

This targets only travel management and duty-of-care receivers, excluding general expense tools that don't handle travel data.

Update Events

After an initial primary event (receipt, booking, invoice, or itinerary) has been posted, you can send update events.

{
  "event_type": "transit_route.status.updated",
  "schema_version": "2.3.0",
  "transaction_id": "txn_6b408ba7406b4754b7b7d287e0ca9fdf"
}

A transaction_id is required for updates; update events will not be accepted without one.

At this time, all update events are organized hierarchically by itemization type.

Transit Route

As with receipt registration, update event data payloads are not included with the event registration. Instead, the payload is encrypted and sent as part of the webhook delivery to receivers returned by the registry.

Transit Route Status Updated

Transit Route Status Updated

Event Type: transit_route.status.updated

{
  "status": "departed",
  "transit_route_item_index": 0,
  "updated_at": 1713196492
}
FieldTypeDescription
statusenumOne of departed or arrived.
transit_route_item_indexnullable integerThe ordered index of the route item to be updated from the original event. If left null, it should be interpreted as 0.
updated_atintegerThe timestamp of the update, measured in seconds since the Unix epoch.
Transit Route Location Updated

Transit Route Location Updated

Event Type: transit_route.location.updated

{
  "lat": 37.7749,
  "lon": -122.4194,
  "transit_route_item_index": 0,
  "updated_at": 1713196492
}
FieldTypeDescription
latnumberLatitude, represented as a floating point number.
lonnumberLongitude, represented as a floating point number.
transit_route_item_indexnullable integerThe ordered index of the route item to be updated from the original event. If left null, it should be interpreted as 0.
updated_atintegerThe timestamp of the update, measured in seconds since the Unix epoch.