Paystack
Adapter 0.1.0, documentation reviewed 2026-10-25. Overall status: limited.
Capabilities
| Error decoding | limited |
| API response parsing | supported |
| Webhook / notification parsing | limited |
| Timeline | limited |
| Event correlation | limited |
| Diagnostic rules | limited |
Supported input
| Format | Description | Status |
|---|---|---|
paystack.api_response | API responses whose data is a transaction (initialize, verify, fetch, charge_authorization and Charge API states such as send_pin, send_otp, pay_offline and pending), a refund, a dispute or a transfer | supported |
paystack.api_error | Error responses (status false, message, type, code, meta.nextStep), including the swapped type and code enums and the string status of the error template | limited |
paystack.webhook | Webhooks with semantics: charge.success, charge.failed, charge.dispute.create, charge.dispute.remind, charge.dispute.resolve, refund.*, transfer.success, transfer.failed, transfer.reversed and bank.transfer.rejected | limited |
paystack.list_response | Paginated list responses (data array with meta.perPage); recognized, not analyzed | unsupported |
paystack.other_webhooks | Preauthorization, direct debit, subscription, invoice, payment request, customer identification and dedicated account events; recognized and shown without semantics | unsupported |
paystack.webhook_delivery_records | Webhook event API delivery records (/integration/webhooks/events); not analyzed | unsupported |
Notification delivery
- Repeated deliveries are recognized by no documented key (webhook bodies carry no event id); Paystack documents that notifications can be delivered more than once.
- Delivery order: not documented by the provider.
- Paystack documents that an endpoint can receive an event more than once, especially on retries, and advises checking a unique transaction reference or resource id before giving value. Webhook bodies carry no event id or timestamp, so verify the transaction (GET /transaction/verify/{reference}) and record what you have already fulfilled.
Known limitations
- Documentation access: the developer documentation at paystack.com/docs answers scripted clients with a challenge page, so its prose (webhook guide, API reference introduction, transfer guides) was not read. The research relies on Paystack's official OpenAPI specification, the official repository of the documentation's code snippets and response examples, and the Help Center. Anything that would only come from the unread prose is treated as not documented.
- Declines are free text; Paystack payloads carry no numeric decline, issuer response, 3-D Secure or AVS code. Only the exact documented messages are decoded (case, apostrophes and spacing are ignored). Any other text is shown as received and decoded as unknown with insufficient confidence.
- Paystack's Help Center does not say which API field carries its error messages. gateway_response and the transaction message are both checked; the top-level message of a response is only used for request errors.
- Webhook bodies have no event id, delivery id or timestamp, so no delivery key is set and repeated deliveries of one event are not reported as duplicates. The retry schedule, maximum attempts, timeout, delivery order and source IPs are not documented in the sources read.
- The x-paystack-signature header (HMAC-SHA512 of the body with the secret key) cannot be verified from pasted data, so a pasted webhook is never treated as authentic. Only the presence of the header is used, as supporting detection evidence.
- The OpenAPI Error schema puts validation_error, processor_error and api_error on code, while every example puts them on type. Both placements are accepted. processor_error has no documented meaning. Many errors carry only status and message; a message-only error is recognized only when the message is one of the documented API error messages.
- The error template shows status as the string "false"; it is accepted only together with a documented error type or meta.nextStep. The direct debit example uses metadata.nextStep instead of meta.nextStep; both are read.
- The envelope status is the request result, not the payment result (a failed charge can come with status true, and the submit-address example has status false with a charge in data). The payment outcome is taken from data.status only.
- The documented HTTP status codes disagree between the specification and the examples for several errors, so the HTTP status is shown but not used to classify errors.
- abandoned is shown as a payment that ended without completing (cancellation stage), not as a decline: Paystack says such a transaction never began. reversed is shown as a reversal of a paid transaction.
- charge.failed appears only in Paystack's events catalog, without a payload example. It is read as the documented transaction object.
- Transfers are payouts and are kept separate from payments. The transfer statuses abandoned, blocked, rejected and received have no documented meaning and are shown as unknown. Transfer failure reasons are not documented (failures is null in every example), so a failed transfer has no decoded reason. A transfer initiate response can say "Transfer has been queued" with status success and no transferred_at; such a response is shown with an unknown outcome.
- Refund webhooks carry no timestamp and, in the documented example, no refund id; they are linked to the payment only through transaction_reference. The refund reason values are not documented and are not shown.
- Disputes are linked through the embedded transaction (reference and id); dispute outcomes are decided by issuing banks and card schemes, and the dispute event is shown without an outcome. dueAt and resolvedAt are shown as supplied.
- bank.transfer.rejected is decoded from message_type INCORRECT_AMOUNT only; other message_type values and the other fields of this event are not documented, so it carries no reference.
- Preauthorization, direct debit, subscription, invoice, payment request, customer identification and dedicated account events are recognized but shown without semantics. Paginated list responses and webhook delivery records are recognized as Paystack data but not analyzed.
- The documented examples disagree on field types (amount as a string in some refund events, exp_month as an integer, metadata as 0, an empty string or an object, gateway_response as an object in the preauthorization example). Amounts are read as integers or digit strings in minor units; other variants are ignored.
- Merchant sectors: the Supported businesses article lists cryptocurrency, forex trading, betting and lotteries, while the Ineligible businesses article excludes them in some or all countries and requires prior approval for gambling. Both are recorded; a listed sector does not mean a merchant will be approved.
- Category and retry guidance per message are PandaPayLens suggestions derived from Paystack's documented meanings, using Paystack's own advice where it gives one (for example retrying after 24 hours).
Examples
- Paystack: card payment with PIN and OTP: Initialize, Charge API steps, the charge.success webhook and verify in one payment.
- Paystack: declined, do not honour: A failed verify response decoded from Paystack's documented bank messages.
Provider documentation
- Paystack developer documentation
- Paystack OpenAPI specification (PaystackOSS/openapi)
- Response and webhook examples of the developer documentation (PaystackOSS/doc-code-snippets)
- API error format example
- Webhook event payload examples
- Refund event payload examples
- Help Center: Bank errors
- Help Center: Customer errors
- Help Center: Fraud block errors
- Help Center: System errors
- Help Center: Abandoned payments
- Help Center: Understanding refund statuses
- Help Center: Viewing and retrying webhooks
- Help Center: Transfers guide for gaming merchants
- Help Center: Supported businesses
- Help Center: Ineligible businesses
PandaPayLens is not affiliated with Paystack. Pasted notifications are never treated as verified: PandaPayLens does not check webhook signatures.