Overview & Event Types

What are webhooks?

Webhooks are server-to-server HTTP callbacks. When something changes in Inflow (a payment is authorized, a subscription is canceled, a withdrawal completes, etc.), we send a POST request to the URL you registered.

Compared to polling GET /api/payment, webhooks:

  • Reduce latency — you learn about changes as they happen
  • Lower API usage — no repeated status checks
  • Carry the same resource payloads you would get from the API (e.g. full payment object)

Deliveries are handled by Svix. Each request is signed; you must verify the signature before trusting the body.

How delivery works

  1. An event occurs on your account (or on a Connect sub-merchant).
  2. Inflow sends a message to your Svix application with an event type (e.g. payment.authorized or connect.payment.authorized).
  3. Svix POSTs to your endpoint. The body is often a batch (array under data).
  4. Your server verifies the signature, returns 2xx within 15 seconds, and processes the event (ideally asynchronously).
Inflow API  →  Svix  →  POST https://yourserver.com/webhooks/inflow
                         Headers: svix-id, svix-timestamp, svix-signature

Register endpoints with Setting up webhooks. Filter which event types you receive via Managing webhooks.

HTTP body format (Svix Stream)

Every delivery is a JSON object with a data array (batched stream). Each element has eventType (route on this) and payload.

Connect (marketplace) — outer name is prefixed; payment lives inside the wrapper:

{
  "data": [
    {
      "eventType": "connect.payment.authorized",
      "payload": {
        "object": "connect_event",
        "eventType": "payment.authorized",
        "subMerchant": { "id": "usr_…", "merchantName": "Seller Alpha" },
        "data": { "id": "pay_…", "status": "CHECKOUT_SUCCESS", "…": "…" }
      }
    }
  ]
}

Direct merchant — no wrapper; payload is the resource (same as the API):

{
  "data": [
    {
      "eventType": "payment.authorized",
      "payload": { "id": "pay_…", "status": "CHECKOUT_SUCCESS", "…": "…" }
    }
  ]
}
  • data[].eventType — Svix event name (connect.* for marketplaces, unprefixed for direct merchants). Use this for routing and endpoint filters.
  • data[].payload — Direct: resource body (GET /api/payment/{id}, etc.). Connect: connect_event wrapper; read the payment (or other resource) from payload.data.
  • payload.eventType (Connect only) — base name without connect. (e.g. payment.authorized). Convenience duplicate of the inner event; prefer data[].eventType for routing.

Always verify using the raw request body and the svix-* headers. Do not re-serialize JSON before verification.

Direct merchant vs Connect (marketplace)

Inflow has two webhook “namespaces”. Which one you receive depends on who owns the account that registered the webhook and where the activity happened.

Direct merchantConnect (marketplace)
Who registers the webhookDirect merchant (INDIVIDUAL)Marketplace (MARKETPLACE)
Event type prefixNone — e.g. payment.settledconnect. — e.g. connect.payment.settled
What triggers deliveryActivity on your merchant accountActivity on any of your sub-merchants (fan-out from Connect)
Default subscription (if you omit eventTypes on create)All direct event typesAll connect.* event types
Typical useYour own checkout, subscriptions, payoutsPlatform monitoring sellers you onboarded via Connect

Direct merchant events

Subscribe to names like payment.created, subscription.active, withdrawal.completed.

The payload is the resource itself (payment, subscription, withdrawal, etc.) — the same JSON shape as the corresponding API.

Connect (marketplace) events

When a sub-merchant (created under your marketplace) has activity, Inflow sends a connect.* event to your marketplace webhook endpoints.

The connect_event object is what you find at data[].payload (not the HTTP root). Structure:

FieldMeaning
objectAlways connect_event
eventTypeBase event name without the connect. prefix (e.g. payment.authorized)
subMerchant.idSub-merchant user id (usr_…)
subMerchant.merchantNameDisplay name, or null if unset
dataFull resource — same shape as GET /api/payment/{paymentId} when the event is payment-related (status, timeline, products, etc.)

The outer data[].eventType is the prefixed Svix name (e.g. connect.payment.authorized). That is what you subscribe to on the endpoint and what you should switch on in code.

Sub-merchants do not receive their own webhook fan-out to the marketplace URL. Register webhooks on the marketplace API key and listen for connect.* only.

Payment status → webhook event (direct & connect)

Internal payment statuses map to dot-notation webhook events:

Payment status (API / timeline)Webhook event type
INITIATIONpayment.created
CHECKOUT_PENDINGpayment.pending
CHECKOUT_SUCCESSpayment.authorized
PAYMENT_SUCCESSpayment.settled
PAYMENT_FAILEDpayment.failed
CHECKOUT_CANCELED / CANCELEDpayment.canceled
REFUND_PENDINGpayment.refund_pending
PARTIAL_REFUNDEDpayment.partially_refunded
FULLY_REFUNDEDpayment.fully_refunded

Payment status rows that include DISPUTE_* labels on the payment timeline do not emit dispute.* webhooks. Those events are delivered only from the dispute pipeline (DISPUTE_CREATEDWebhookDisputeDto payload, including evidenceDueAt), with event types mapped from DisputeStatus (OPENEDdispute.opened, UNDER_REVIEWdispute.under_review, etc.).

For Connect, payment mappings use the connect. prefix (e.g. connect.payment.authorized on CHECKOUT_SUCCESS). Dispute events use connect.dispute.* with the same connect_event wrapper.

Available event types

List direct (unprefixed) event types programmatically:

curl https://api.inflowpay.xyz/api/webhook/event-types \
  -H "X-Inflow-Api-Key: inflow_prod_your_key"

This endpoint returns SVIX_EVENT_TYPE_DEFINITIONS only — names like payment.settled, not connect.payment.settled. Marketplaces subscribe to connect. + the same base name (e.g. connect.payment.settled). You can pass those names on create and on PATCH /api/webhook/{webhookId}/event-types even though they are not listed by GET /api/webhook/event-types.

Descriptions below match the Svix event-type registry in the API.

Payment

Event typeDescription
payment.createdA new payment has been created
payment.pendingPayment is pending (checkout awaiting completion)
payment.authorizedPayment has been authorized (funds received by provider)
payment.settledPayment has been settled (crypto delivered to wallet)
payment.failedPayment has failed
payment.canceledPayment has been canceled
payment.expiredPayment has expired without completion (registered in Svix; not emitted by status handlers today)
payment.refund_pendingA refund is being processed for this payment
payment.partially_refundedPayment has been partially refunded
payment.fully_refundedPayment has been fully refunded

Subscription

Event typeDescription
subscription.createdA new subscription has been created
subscription.activeSubscription is now active
subscription.trial_startedSubscription trial period has started
subscription.past_dueSubscription payment is past due
subscription.canceledSubscription has been canceled
subscription.pending_cancellationSubscription is pending cancellation at period end

Deposit (virtual account)

Event typeDescription
deposit.funds_receivedFunds have been received on the virtual account
deposit.payment_submittedDeposit payment has been submitted for processing
deposit.payment_processedDeposit payment has been processed successfully
deposit.in_reviewDeposit is under review
deposit.refundedDeposit has been refunded

Dispute

Event typeDescription
dispute.openedA dispute has been opened on a payment
dispute.evidence_submittedEvidence has been submitted for the dispute (registered in Svix; not emitted by dispute handlers today)
dispute.under_reviewDispute is under review by the payment processor
dispute.wonDispute has been resolved in your favor
dispute.lostDispute has been lost
dispute.acceptedDispute has been accepted (merchant conceded)

Withdrawal

Event typeDescription
withdrawal.initiatedA withdrawal has been initiated
withdrawal.submittedWithdrawal has been submitted for processing
withdrawal.processingWithdrawal is being processed
withdrawal.completedWithdrawal has been completed successfully
withdrawal.failedWithdrawal has failed
withdrawal.canceledWithdrawal has been canceled
withdrawal.returnedWithdrawal funds have been returned

Swap

Event typeDescription
swap.initiatedA currency swap has been initiated
swap.pendingSwap is pending (outbound transfer in progress)
swap.processingSwap is being processed (cross-chain conversion in progress)
swap.completedSwap has been completed successfully
swap.failedSwap has failed
swap.canceledSwap has been canceled
swap.refundedSwap funds have been refunded

Connect mirrors

Every row above has a Connect counterpart: prefix connect. to the event name.

Examples: connect.payment.settled, connect.subscription.active, connect.withdrawal.completed.

Marketplaces should subscribe only to the connect.* names they care about.

Legacy events (V1 webhooks only)

Older webhook endpoints may still receive legacy snake_case types:

  • payment_created
  • payment_status_updated

New endpoints use V2 dot notation (payment.created, payment.authorized, …). When creating a webhook today, you only receive V2-style types (or their connect.* mirrors for marketplaces).

Subscribing to specific events

On create, pass eventTypes:

curl -X POST https://api.inflowpay.xyz/api/webhook \
  -H "X-Inflow-Api-Key: inflow_prod_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourserver.com/webhooks/inflow",
    "eventTypes": [
      "connect.payment.authorized",
      "connect.payment.settled"
    ]
  }'

Update later with PATCH /api/webhook/{webhookId}/event-types. The list replaces the full subscription — omit an event type to stop receiving it.

Passing an empty eventTypes array subscribes to all events for your account type. See Managing webhooks.

Next steps