1. Webhooks
Tranzakt APIs
  • Introduction
  • Collections
    • Get Collection by ID
      GET
    • Get Collection Invoices
      GET
  • Invoices
    • Create Invoice
      POST
    • Get Invoice by ID
      GET
    • Invalidate Invoice
      POST
  • Webhooks
    • Webhooks 🔔
  1. Webhooks

Webhooks 🔔

Welcome to our webhooks documentation! This section outlines how the Tranzakt Payment Platform (TPP) delivers webhook notifications to your systems after payment events occur. Our webhook system ensures you receive real-time updates about payment events in your application without needing to poll our API.

Overview#

Our webhook system allows you to:
Receive real-time payment notifications
Automate order fulfillment processes
Update customer accounts instantly
Track payment statuses without polling
Implement event-driven architecture
Build reliable payment flows

Webhook Architecture#

After a successful payment through the Tranzakt platform, our system sends an HTTP POST request to the callback URL you specified when creating the invoice. This enables your application to react immediately to payment events as they occur.
Every webhook we send is signed with your secret key, so you can confirm the request genuinely came from Tranzakt before you act on it. See Verifying the Webhook Signature.

POST Payment Webhook#

Endpoint Setup#

To receive webhooks, you need to:
1.
Create a publicly accessible HTTPS endpoint in your application
2.
Specify this endpoint as the webhook when creating an invoice or use deafult webhook on the collection or API settings
3.
Implement proper response handling at your endpoint
4.
Verify the X-Tranzakt-Signature header before processing the payload

Request Details#

Method: POST
Content-Type: application/json
Timeout: 30 seconds (requests taking longer will be terminated)

Headers#

HeaderValueDescription
Content-Typeapplication/jsonFormat of the request body
Acceptapplication/jsonExpected response format
User-AgentTranzakt-Payment-Platform/1.0Identifies our platform
X-Webhook-IDUUID stringUnique identifier for the webhook event
X-Tranzakt-SignatureLowercase hex stringHMAC SHA512 signature of the raw request body, signed with your secret key

Request Body#

{
  "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "event": "payment.successful",
  "createdAt": "2024-05-20T10:15:30.123Z",
  "data": {
    "id": "22205053-02c7-4607-9cb5-5fa58cecae6d",
    "collectionId": "37a71e2e-ed54-4e46-a3a9-47a211c352ea",
    "collectionName": "Product Sales",
    "title": "Checkout Invoice",
    "amount": 40000,
    "totalAmount": 40400,
    "serviceCharge": 400,
    "vat": 0,
    "payerName": "John Doe",
    "payerEmail": "john.doe@example.com",
    "payerPhoneNumber": "07078955432",
    "billerName": "Example Business",
    "billerEmail": "sales@example.com",
    "billerAddress": "123 Business St",
    "type": "Live",
    "status": "Paid",
    "paymentMethod": "Card",
    "paymentDate": "2024-05-20T10:15:30.123Z",
    "billerMetaData": {
      "order-id": "12345"
    },
    "callBackUrl": "https://your-api.com/webhooks/tranzakt",
    "dateCreated": "2024-05-20T10:00:00.000Z"
  }
}

Request Body Fields#

FieldTypeDescription
idstringUnique identifier for the webhook notification
eventstringType of event that triggered the webhook (e.g., payment.successful)
createdAtstringISO 8601 timestamp when the webhook was generated
dataobjectContains the complete invoice information
data.idstringInvoice ID
data.collectionIdstringCollection ID associated with this invoice
data.collectionNamestringName of the collection
data.titlestringInvoice title
data.amountnumberBase amount in kobo/cents
data.totalAmountnumberTotal amount including fees in kobo/cents
data.serviceChargenumberService charge in kobo/cents
data.vatnumberVAT amount in kobo/cents
data.payerNamestringName of the payer
data.payerEmailstringEmail of the payer
data.payerPhoneNumberstringPhone number of the payer
data.billerNamestringYour business name
data.billerEmailstringYour business email
data.billerAddressstringYour business address
data.typestringInvoice type (Test or Live)
data.statusstringInvoice status (will be Paid for successful payments)
data.paymentMethodstringMethod used for payment (e.g., Card, BankTransfer)
data.paymentDatestringISO 8601 timestamp when payment was made
data.billerMetaDataobjectCustom metadata you provided when creating the invoice
data.callBackUrlstringThe URL receiving this webhook
data.dateCreatedstringISO 8601 timestamp when the invoice was created

Expected Response#

Your server should respond with a 2xx status code (preferably 200 OK) to acknowledge receipt of the webhook. The response body is not used by our system.
Status: 200 OK

Verifying the Webhook Signature#

Every webhook includes an X-Tranzakt-Signature header. This lets you confirm the request came from Tranzakt and that the payload was not altered in transit. Always verify it before you act on a webhook.

How the signature is generated#

We compute an HMAC SHA512 hash of the exact JSON body we send, using your secret key as the HMAC key, and send the result as a lowercase hexadecimal string.
PropertyValue
HeaderX-Tranzakt-Signature
AlgorithmHMAC SHA512
KeyYour secret key
MessageThe raw request body, exactly as received
EncodingLowercase hexadecimal

Which secret key is used#

We sign with the active secret key that matches your current API mode. If your account is in test mode we sign with your test secret key, and if it is in live mode we sign with your live secret key. You can find both in your dashboard under API settings.
Use the same key on your side. If you handle both modes on one endpoint, choose the key using the data.type field in the payload, which is Test or Live.

Important#

Hash the raw request body exactly as you received it. Do not parse the JSON and serialise it again before hashing. Our payload is sent formatted, so any reserialisation will change the bytes and the signature will not match. Most frameworks discard the raw body by default, so you usually need to capture it explicitly. The example below shows how.
Compare the two values using a timing safe comparison rather than a plain string equality check.

Node.js (Express) verification#

PHP verification#

Python (Flask) verification#

C# (ASP.NET Core) verification#


Implementation Notes#

1.
Idempotency: The same webhook may be sent multiple times if we don't receive a timely response. Implement idempotency using the webhook id to prevent duplicate processing.
2.
Retry Logic: We will retry failed webhook deliveries (non-2xx responses or timeouts) up to 3 times with exponential backoff.
3.
Webhook Security: We recommend validating the webhook source by:
Verifying the X-Tranzakt-Signature header on every request, and rejecting anything that does not match
Using HTTPS for your endpoint
Implementing IP allowlisting (contact support for current IP ranges)
Verifying the webhook data against your database records
4.
Timeout: Webhooks must be processed within 30 seconds, or the connection will be terminated. For long-running tasks, acknowledge the webhook quickly and process asynchronously.
5.
Keep your secret key private: Your secret key is what proves a webhook came from us. Never expose it in client side code or commit it to source control. If you believe it has been exposed, rotate it in your dashboard, and remember that webhooks are signed with the new key from that point on.

🔐 Security Note: Always validate incoming webhooks to ensure they originate from Tranzakt before processing them. Verifying the X-Tranzakt-Signature header is the strongest way to do this.

Code Example#

Node.js (Express) Implementation#


Event Types#

Event TypeDescription
payment.successfulSent when a payment is successfully completed
More event types will be added in future releases.

Troubleshooting#

If you're not receiving webhooks as expected:
1.
Check your callback URL: Ensure it's publicly accessible and correctly specified when creating invoices
2.
Verify your endpoint: Test it with tools like Postman to confirm it can receive POST requests
3.
Check response codes: Your endpoint must return a 2xx status code within 30 seconds
4.
Review logs: Examine your logs for any errors in webhook processing
5.
Contact support: If issues persist, contact Tranzakt support for assistance
If the signature never matches:
1.
Check you are hashing the raw body: Reserialising the parsed JSON will change the bytes and break the signature. Capture the raw body before your JSON parser touches it.
2.
Check you are using the right key: Test mode webhooks are signed with your test secret key, live mode with your live secret key.
3.
Check the encoding: The signature is lowercase hexadecimal, not base64.
4.
Check you are using SHA512: SHA256 will produce a shorter value that never matches.
⚠️ Remember that webhooks are only delivered if your endpoint is accessible from the internet. Local development servers may need to use a tunneling service like ngrok.

For more assistance, email support at hi@tranzakt.finance
Modified at 2026-08-11 20:51:42
Previous
Invalidate Invoice
Built with