OpenFX uses an event-driven architecture to notify your application when something changes — a payment completes, a customer passes KYB, a conversion settles, or a collection is returned. Instead of polling every endpoint to check for updates, you register a webhook subscription and OpenFX pushes events to your URL in real time.

How it works

  Your Application                        OpenFX Platform
  =================                       ===============

  1. Register webhook subscription
     POST /webhooks/subscriptions    --->  Subscription created (wsub_...)
                                    <---   Signing secret returned (store securely)

  2. Something happens on the platform
     (e.g., payment completes)             Event generated (evt_...)

  3. OpenFX delivers webhook
     POST to your URL               <---   Signed payload with X-OpenFX-Signature

  4. Verify signature                      (Your code verifies HMAC-SHA256)

  5. Process event                         (Your code handles the event)

  6. Return 2xx response             --->  Delivery marked as "delivered"
Every webhook delivery is signed with HMAC-SHA256 using a secret unique to your subscription. Always verify the X-OpenFX-Signature header before processing any webhook payload. See Signature Verification for implementation details.

Webhooks vs polling

OpenFX provides two complementary mechanisms for tracking resource changes:
WebhooksEvents API (GET /events)
Delivery modelPush — OpenFX sends to your URLPull — you poll the endpoint
LatencyNear real-time (seconds)Depends on your poll interval
Best forPrimary event processingRecovery, backfill, audit
OrderingDelivery order not guaranteedChronologically ordered
Reliability3 retries with exponential backoffAlways available
Use webhooks as your primary integration mechanism and the Events API as a fallback for recovery. If your webhook endpoint goes down, you can poll missed events from GET /events once it recovers.

Event domains

OpenFX generates events across 10 resource domains in the MVP. Events follow a consistent naming convention: resource.action (e.g., payment.completed, customer.kyb_status_changed).
DomainEventsKey use cases
Customer3KYB status changes, customer activation
Account2Account creation and status transitions
AccountNumber2Virtual account number provisioning
BlockchainAddress1Crypto deposit address creation
Counterparty3Counterparty lifecycle (create, activate, archive)
PaymentMethod3Payment method validation results
Payment10Full payment lifecycle from creation to completion
Conversion4FX conversion lifecycle
Transfer3Internal transfer completion
Transaction1Ledger entry creation
Onboarding3Orchestrated onboarding completion
Collection7ACH debit collection lifecycle
See Event Types for the complete list with payload details.

Webhook payload structure

Every webhook delivery uses a consistent envelope:
{
  "id": "whd_01953e1a5f4b7100",
  "type": "payment.completed",
  "sequence": 42,
  "createdAt": "2026-02-23T12:05:00Z",
  "data": {
    "resourceType": "payment",
    "resourceId": "pmt_01953e1a5f4b7005",
    "snapshot": {
      "id": "pmt_01953e1a5f4b7005",
      "status": "completed",
      "rail": "ach",
      "sendAmount": {
        "currency": "USD",
        "exponent": 2,
        "amount": "150000",
        "displayValue": "1500.00"
      }
    }
  }
}
The sequence field is a monotonically increasing integer. Use it for ordering events and detecting gaps when polling via GET /events. For .updated and .status_changed events, the payload also includes previousAttributes showing the fields that changed:
{
  "id": "whd_01953e1a5f4b7101",
  "type": "customer.status_changed",
  "createdAt": "2026-02-23T12:03:00Z",
  "data": {
    "resourceType": "customer",
    "resourceId": "cus_01953e1a5f4b7000",
    "snapshot": {
      "id": "cus_01953e1a5f4b7000",
      "status": "active",
      "kybStatus": "approved"
    }
  },
  "previousAttributes": {
    "status": "submitted",
    "kybStatus": "pending"
  }
}

Delivery guarantees

OpenFX provides at-least-once delivery with bounded retries:
  • Retry policy: Failed deliveries are retried up to 3 times with exponential backoff.
  • Success criteria: Your endpoint must return a 2xx HTTP status code within 30 seconds.
  • Failure handling: After 3 failed attempts, the delivery is marked as failed. Persistent failures may cause subscription suspension.
  • Ordering: Event delivery order is not strictly guaranteed. Design your handlers to be idempotent and use the event id for deduplication.
Because webhooks provide at-least-once delivery, your endpoint may receive the same event more than once. Always use the webhook delivery id field to deduplicate events in your processing logic.

Quick start

Get webhooks working in three steps:
  1. Create a subscription — Register your endpoint URL and select event types.
  2. Verify signatures — Implement HMAC-SHA256 verification on your endpoint.
  3. Process events — Handle each event type relevant to your integration.
See Setup & Configuration to begin.

Next steps