Billing events — API/SDK advanced
Forward authenticated payments, refunds and disputes for the API/SDK advanced path with exact amounts and stable identities.
Updated August 3, 2026
This merchant webhook verification and forwarding flow is only for API/SDK advanced. Verify the payment-provider webhook on your server before sending its billing event to AffiHQ. Do not send payment events from a browser callback.
With Stripe automatic, AffiHQ receives, verifies, checks the Stripe mode, retries and processes native Stripe Connect deliveries. Do not forward those same Stripe events from your application or duplicate them through the API. For a native setup issue, see the troubleshooting guide.
Successful payment
await affihq.billingEvents.send({
type: 'payment.succeeded',
provider: 'stripe',
providerEventId: stripeEvent.id,
customerId: merchantCustomerId,
paymentId: invoice.id,
billingCycle: 'monthly',
currency: 'USD',
amounts: {
collectedMinor: 2500,
taxMinor: 0,
discountMinor: 500,
commissionableMinor: 2000,
},
occurredAt: stripeEvent.createdAt,
})
All monetary values use the currency’s minor unit. commissionableMinor cannot exceed the collected amount minus tax. Exclude non-commissionable lines before submitting the event.
Refunds and disputes
Send payment.refunded, payment.disputed and payment.dispute_resolved events with the original paymentId. A correction before payout reduces what is due. A correction after payout becomes a negative balance against future commissions.
Events before attribution
Billing events can arrive before the matching attribution. AffiHQ retains them as unattributed and replays the match when the attribution is locked.
Idempotency
The SDK sends provider:providerEventId as the idempotency key. An identical replay is accepted as a duplicate. If AffiHQ returns idempotency_conflict, compare the financial data with the original event before sending it again.