Webhooks

Events

Every event type Harpoon emits.

Event types

EventTriggered by
transaction.completedSUCCESS, PARTIAL, or OVERPAID
transaction.failedFAILED
transaction.expiredEXPIRED
transaction.refundedREFUNDED
transaction.cancelledCANCELLED
transaction.disputedMANUAL_REVIEW

SUCCESS, PARTIAL, and OVERPAID all share the transaction.completed event. Read data.status and data.difference to disambiguate.

Envelope

JSON
{
  "event": "transaction.completed",
  "webhook_id": "whk_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
  "timestamp": "2026-04-29T12:05:32Z",
  "data": { /* event-specific */ }
}
FieldDescription
eventEvent type
webhook_idStable ID for this delivery. Use it as your idempotency key.
timestampISO 8601, UTC
dataTransaction payload

Payload (data)

JSON
{
  "reference": "hpn_trx_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
  "hpn_code": "K7M3F6",
  "status": "SUCCESS",
  "expected_amount": "150.00",
  "actual_amount": "150.00",
  "difference": null,
  "difference_type": "EXACT",
  "currency": "GHS",
  "payer_phone": "0244123456",
  "telco_provider": "mtn",
  "telco_transaction_id": "73012849466",
  "meta": { "order_id": "1234" },
  "client_reference": "order_1234"
}
FieldTypeNotes
referencestringHarpoon ID
hpn_codestring
statusstringNew state of the payment
expected_amountstring
actual_amountstring | nullnull for expired / cancelled
differencestring | nullSigned: actual - expected
difference_typestring | nullEXACT, UNDERPAID, or OVERPAID
payer_phonestring | nullDisplay format 0XXXXXXXXX
telco_providerstring | nullmtn, telecel, or at
telco_transaction_idstring | null
metaobjectWhatever you sent on initialize
client_referencestring | nullWhatever you sent on initialize

expired, cancelled, failed, refunded, and disputed use the same shape with actual_amount, difference, difference_type, telco_* set to null where they don’t apply.