Open Collections

Payload & Signatures

What we POST to your endpoint.

Event

One event: transaction.forwarded. Fires for every payment a rule on your endpoint claims.

Payload

JSON
{
  "event": "transaction.forwarded",
  "webhook_id": "ocl_a1b2c3d4e5f6g7h8i9j0k1l2",
  "timestamp": "2026-04-29T12:05:32Z",
  "data": {
    "transaction_id": "550e8400-e29b-41d4-a716-446655440000",
    "telco_transaction_id": "73012849466",
    "provider": "mtn",
    "amount": "150.00",
    "currency": "GHS",
    "reference": "ACCT-44821",
    "payer_phone": "0244123456",
    "payer_name": "JOHN DOE",
    "transaction_timestamp": "2026-04-29T12:05:30Z",
    "received_on": {
      "phone_number": "0201234567",
      "provider": "MTN MoMo",
      "account_name": "Adom Ventures",
      "merchant_code": "554120"
    },
    "hpn_matched": false
  }
}
FieldTypeDescription
eventstringAlways transaction.forwarded
webhook_idstringStable id for this delivery, prefix ocl_. Your idempotency key
timestampstringISO 8601, UTC
data.transaction_idstringHarpoon’s id for the payment
data.telco_transaction_idstring | nullProvider transaction ID
data.providerstringmtn, telecel, or at
data.amountstringFixed-decimal string
data.currencystringAlways GHS
data.referencestring | nullThe reference the payer typed
data.payer_phonestring | nullDisplay format 0XXXXXXXXX
data.payer_namestring | nullAs reported by the provider
data.transaction_timestampstringISO 8601, UTC
data.received_onobject | nullWhich of your numbers took the money
data.received_on.phone_numberstringDisplay format 0XXXXXXXXX
data.received_on.providerstringMTN MoMo, Telecel Cash, or AT Money
data.received_on.account_namestringThe name on this number
data.received_on.merchant_codestring | nullThe till on this number
data.hpn_matchedbooleanA Harpoon payment code already matched it. Only true on a rule with include_matched

Headers

HeaderValue
X-Harpoon-Signaturesha256=<hex>
X-Harpoon-Signature-PreviousFor 24 hours after a rotation, signed with the old secret
X-Harpoon-TimestampUnix timestamp
X-Harpoon-Webhook-IDSame as webhook_id in body
Content-Typeapplication/json
User-AgentHarpoon-Webhook/1.0

Verify the signature

Same HMAC-SHA256 scheme as Harpoon webhooks, using the secret from endpoint creation.

For 24 hours after a rotation both signatures are sent: the new one in X-Harpoon-Signature, the old in X-Harpoon-Signature-Previous. Accept either while you change over.

Idempotency

Use webhook_id as your idempotency key. Retries reuse it, and one payment reaches an endpoint once, so transaction_id never arrives twice at the same URL. Resending and replaying reuse the original delivery.

Two endpoints claiming one payment each get their own webhook_id for the same transaction_id. That is one payment reaching two systems, not a duplicate.