Open Collections

Payload & Signatures

What we POST to your endpoint.

Event

Exactly one event: transaction.forwarded. Fires for every incoming MoMo payment that didn’t match an HPN code.

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"
  }
}
FieldTypeDescription
eventstringAlways transaction.forwarded
webhook_idstringStable ID for this delivery, prefix ocl_. Use it as 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 field from the payment — match against your scheme
data.payer_phonestring | nullDisplay format 0XXXXXXXXX
data.payer_namestring | nullAs reported by the provider
data.transaction_timestampstringISO 8601, UTC

Headers

HeaderValue
X-Harpoon-Signaturesha256=<hex>
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 returned at endpoint creation.

Idempotency

Use webhook_id as your idempotency key. Retried deliveries reuse the same webhook_id, and a re-ingest of the same underlying payment is deduplicated server-side — your handler should never need to re-process the same transaction_id.