Webhooks

Event Types

All 13 subscribable webhook events with when they fire and their payload fields.

halfin delivers 13 merchant-subscribable webhook events. New canonical deliveries use the envelope structure { event_id, event, created_at, data }, where event_id is a stable UUID for idempotency.

For compatibility, event_id remains optional in invoice, late-payment, payout, and refund schemas because a retry of a legacy stored payload may omit it. balance.credited always includes event_id.

Invoice events

All invoice events use the InvoiceWebhookData payload:

FieldTypeRequiredDescription
invoice_iduuidyesInvoice UUID
external_idstringyesYour external reference (null if not set)
currencystringyesCurrency code
networkstringnoBlockchain network of the immutable amount snapshot
environmentstringyeslive or test
amount_requestedstringyesRequested amount (decimal string)
amount_paidstringyesTotal paid so far (decimal string)
statusstringyesInvoice status at event time
amount_fiatstringnoFiat-nominated amount (fiat-denominated invoices only)
fiat_currencystringnoFiat currency code (e.g. "USD")
paid_atdatetimenoPayment timestamp (invoice.paid and invoice.overpaid only)
expires_atdatetimenoExpiry timestamp (invoice.expired only)
sourcestringno"static_address" for auto-created invoices
static_address_iduuidnoStatic address UUID (static address invoices only)
gross_amountstringnoGross receivable before fees (decimal string). Present on invoice.paid and invoice.overpaid for passthrough credits.
fee_totalstringnoTotal service fee on the credit (decimal string)
net_amountstringnoNet amount credited to merchant balance (decimal string)
feesarraynoPer-fee breakdown: [{ type, amount, payer }]. Payer is merchant, payer, or halfin.
reversed_amountstringnoSource amount reversed by invoice.payment_reversed
reversed_currencystringnoSource currency of the reversed payment
reversed_networkstringnoSource network of the reversed payment

invoice.confirming

Fires when the first on-chain payment is detected for an invoice. Confirmations are still pending.

invoice.paid

Fires when the invoice amount is met and the required number of blockchain confirmations is reached. Safe to fulfill the order.

invoice.overpaid

Fires when the total amount received exceeds the requested amount. Treat the same as invoice.paid for fulfillment.

invoice.underpaid

Fires when the invoice expires after receiving a partial payment below the underpayment threshold.

invoice.expired

Fires when an invoice reaches its TTL without being fully paid.

invoice.late_payment

Fires when a payment arrives after the invoice has already expired. Uses LatePaymentWebhookData:

FieldTypeRequiredDescription
invoice_iduuidyesInvoice UUID
external_idstringyesYour external reference (null if not set)
currencystringyesCurrency code
networkstringnoBlockchain network of the triggering late payment
environmentstringyeslive or test
amount_requestedstringyesOriginal requested amount
late_payment_amountstringyesAmount of the late payment (decimal string)
amount_usdstringnoLegacy USD-denominated requested amount, when available
amount_fiatstringnoFiat-denominated requested amount, when available
fiat_currencystringnoFiat currency code paired with amount_fiat
statusstringyesInvoice status (always "expired")
sourcestringno"static_address" for auto-created invoices
static_address_iduuidnoStatic address UUID
gross_amountstringnoGross receivable before fees (decimal string). Present for passthrough credits.
fee_totalstringnoTotal service fee on the late credit (decimal string)
net_amountstringnoNet amount credited to merchant balance (decimal string)
feesarraynoPer-fee breakdown: [{ type, amount, payer }]
rate_appliedstringnoCrypto-to-USD rate used for a static-address credit
rate_updated_atdatetimenoTimestamp of the exchange rate used for a static-address credit
rate_age_msintegernoAge of the applied rate in milliseconds
rate_stalebooleannoWhether the applied rate exceeded its freshness threshold

invoice.payment_reversed

Fires when a previously confirmed payment is reversed due to a blockchain reorganization. The invoice amount_paid is recalculated. Canonical deliveries identify the affected source amount with reversed_amount, reversed_currency, and reversed_network. These fields remain optional for compatibility with legacy stored payloads.


Balance event

balance.credited

Fires only after the merchant's available balance is credited. Use this as the fulfillment signal when balance availability matters. Includes a stable event_id for idempotency.

FieldTypeRequiredDescription
invoice_iduuidyesInvoice UUID
payment_iduuidyesPayment row UUID
external_idstringnoYour external reference
outcomestringyesBalance credit outcome
source_amountstringyesOriginal deposit amount
source_currencystringyesDeposit currency
source_networkstringyesDeposit network
credited_amountstringyesAmount added to merchant balance
credited_currencystringyesCredited balance currency
credited_networkstringyesCredited balance network
gross_amountstringnoGross amount before fees
fee_amountstringnoPlatform service fee
net_amountstringnoNet credited amount

Payout events

payout.completed

Fires when a payout is confirmed on-chain.

FieldTypeRequiredDescription
payout_iduuidyesPayout UUID
currencystringyesCurrency code
networkstringyesBlockchain network
environmentstringyeslive or test
amountstringyesBase requested payout amount
recipient_amountstringyesAmount sent to the recipient after customer-allocated charges
merchant_debit_amountstringyesTotal merchant debit including merchant-allocated charges
destinationstringyesDestination address
tx_hashstringyesOn-chain transaction hash
network_feestringyesActual on-chain network fee
fee_amountstringyesPlatform payout fee
payout_fee_allocationstringyesWhether the payout fee is allocated to customer or merchant
configured_network_fee_amountstringyesSnapshotted commercial network charge
network_fee_allocationstringyesWhether the commercial network charge is allocated to customer or merchant
statusstringyesAlways "completed"

payout.failed

Fires when a payout fails. Reserved funds are released back to the merchant balance.

FieldTypeRequiredDescription
payout_iduuidyesPayout UUID
currencystringyesCurrency code
networkstringyesBlockchain network
environmentstringyeslive or test
amountstringyesBase requested payout amount
recipient_amountstringyesAmount intended for the recipient after customer-allocated charges
merchant_debit_amountstringyesMerchant debit reserved for the failed payout
fee_amountstringyesSnapshotted platform payout fee
payout_fee_allocationstringyesWhether the payout fee is allocated to customer or merchant
configured_network_fee_amountstringyesSnapshotted commercial network charge
network_fee_allocationstringyesWhether the commercial network charge is allocated to customer or merchant
destinationstringyesDestination address
error_messagestringyesError description
statusstringyesAlways "failed"

Refund events

All refund events use RefundWebhookData:

FieldTypeRequiredDescription
refund_iduuidyesRefund UUID
invoice_iduuidyesInvoice UUID being refunded
payout_iduuidyesLinked payout UUID
currencystringyesRefunded currency
networkstringyesRefunded network
environmentstringyeslive or test
amountstringyesBase requested refund amount
recipient_amountstringyesAmount sent to the customer after customer-allocated charges
merchant_debit_amountstringyesTotal merchant debit including merchant-allocated charges
refund_feestringyesPlatform refund fee
refund_fee_allocationstringyesWhether the refund fee is allocated to customer or merchant
network_feestringyesActual on-chain network fee after completion
configured_network_fee_amountstringyesSnapshotted commercial network charge
network_fee_allocationstringyesWhether the commercial network charge is allocated to customer or merchant
destinationstringyesDestination address
destination_tagstringyesMemo/tag if applicable; null when absent
statusstringyespending, completed, or failed
tx_hashstringyesTransaction hash when completed; null otherwise
failure_reasonstringyesProcessor failure reason when failed; null otherwise
error_messagestringnoAdditional error description for refund.failed

refund.created

Fires when a refund is created and the linked payout is queued for execution.

refund.completed

Fires when the linked payout completes on-chain. Includes tx_hash and the actual network fee.

refund.failed

Fires when the linked payout fails and the refund reservation is released back to the merchant balance.