Events

While the Versa protocol's main usecase is the transmission of receipts, other event types and associated payloads can be registered by the same mechanism.

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:

  • itinerary - Itinerary data events containing travel booking information
  • receipt - Receipt data events containing purchase/transaction details (a superset of itinerary data)
  • 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.1.0",
    "handles": {
      "customer_email_domain": "acme.co"
    }
  }'

Request Parameters

FieldTypeDescription
event_typestringOptional. Filter receivers by transaction event type. Valid values: "receipt", "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.

Itineraries

When sending travel booking confirmations that do not have payment details attached, you can register an itinerary event:

{
  "event_type": "itinerary",
  "schema_version": "2.1.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 receipt or itinerary has been posted, you can send update events.

{
  "event_type": "transit_route.status.updated",
  "schema_version": "2.1.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 receipt or itinerary. 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 receipt or itinerary. If left null, it should be interpreted as 0.
updated_atintegerThe timestamp of the update, measured in seconds since the Unix epoch.