Skip to main content

Command Palette

Search for a command to run...

The Architecture Audit: Moniepoint POS API

Audit Series #1 Focus: Async Flows, Status Gaps, and Reference Ambiguity

Updated
7 min read
The Architecture Audit: Moniepoint POS API

Executive Summary

Moniepoint's POS API documentation is technically solid. The architecture makes sound choices, asynchronous patterns, webhook notifications for real time updates, and a clean scope-based authentication model. But the documentation doesn't fully explain how these pieces work together.

The current docs focus on what each endpoint does, but leave out the how. Specifically, how a transaction moves from from initiation to confirmation, what the two status fields actually mean, and what developers need to know about the references they receive and send.

This audit identifies five specific gaps and recommends practical fixes for each.

The Findings

No guidance on how often to check transaction status

When a transaction is submitted, Moniepoint returns a 202 Accepted response, meaning "we got it, but it's still being processed." Developers then need to check back using a GET endpoint to find out the final status.

The problem: The docs warn that checking too frequently may trigger rate limiting, but they don't say how frequently is too frequent, or what the right approach is.

A warning without a solution: developers are told what not to do, but not what to do instead.

What's missing:

•       A note that the 202 response returns no body the merchantReference is the only handle developers have to retrieve transaction status later

•       A recommended polling schedule (e.g. check at 2s, then 5s, then 15s)

•       An explanation of when to stop polling and treat a transaction as failed

•       A sequence diagram showing the full push → poll → webhook flow

Webhook events can arrive more than once and the docs don't say so

In distributed systems, it's common, and expected, for webhook notifications to be delivered more than once. This is standard practice, not a bug. Moniepoint's own resend endpoint confirms this, it explicitly supports resending PENDING and FAILED events, meaning duplicate delivery is a built-in feature of the system.

The practical consequence here is lower-stakes than in some payment systems, since this API initiates a payment rather than recording a credit, a duplicate webhook means a duplicate notification, not a duplicate charge. But it can still cause problems: a merchant system that hasn't accounted for duplicates may trigger redundant fulfilment logic, send a customer two confirmation messages, or update an order status incorrectly.

The docs mention merchantReference but don't explain its role in identifying whether an incoming webhook has already been processed.

The API supports resending events, confirming duplicates will arrive. Developers are never told to expect them

What's missing:

•       A clear statement that duplicate webhook delivery can and will occur

•      Guidance on using merchantReference as the idempotency key to detect and safely ignore duplicate events

•      A note on what downstream effects to guard against in the merchant's own system

Two status fields with no explanation of which one to trust

Transaction responses include two separate status fields: processingStatus and queueStatus. The docs list both, but don't explain the relationship between them.

For example: if queueStatus is SUCCESS but processingStatus is PENDING, what does that mean? Should the developer consider the transaction complete? Still waiting? At risk of failing?

Without clarity here, developers add extra defensive code "just in case", which slows down the payment flow and introduces unnecessary complexity.

Two status fields, one response, no explanation of which one to trust.

What's missing:

•       A plain-language explanation of what each status field represents

•       A state map showing the possible combinations and what each one means

•       A clear rule for which field is the definitive source of truth

Two transaction references exist, but only one is explained

The transaction flow involves two distinct reference identifiers. The merchantReference is generated by the developer and sent with the initial request. The transactionReference is generated by Moniepoint and returned in the transaction details response once payment is complete.

These are not the same thing, and they serve different purposes, but the documentation never explains the distinction. The transactionReference appears in the GET response payload, and a developer could easily overlook it or conflate it with the merchantReference they already sent.

This matters because the transactionReference is Moniepoint's own record of the transaction. It is the authoritative identifier on Moniepoint's side, useful for support queries, reconciliation, and audit trails. A developer who doesn't know it exists won't store it, and will have a much harder time resolving disputes or tracing failed payments.

What's missing:

•       A clear explanation of the difference between merchantReference and transactionReference

•       A note that transactionReference is Moniepoint's identifier and should be stored by the merchant system

•       Guidance on when each reference should be used, e.g. merchantReference for polling, transactionReference for reconciliation and support

The 202 response returns no body, and the docs don't say so

When a developer pushes a transaction using POST /v1/transactions, the API returns a 202 Accepted response with no body. No transaction ID, no confirmation token, nothing.

This means the merchantReference the developer sends in the request is the only way to look up that transaction later. If it isn't unique, stored, or retrievable, the developer has no way to check what happened.

The docs don't flag this dependency. The merchantReference field is listed as a required string, but its critical role as the sole transaction identifier after submission is never explained.

A successful response that returns nothing. The merchantReference you sent in is now your only way back.

What's missing:

•       An explicit note that the 202 response returns no body

•       A clear statement that merchantReference is the only handle for retrieving transaction status after submission

•       Guidance on merchantReference format, it should be unique per transaction and stored on the client side before the request is sent

Recommendations

These five changes would significantly reduce integration friction:

1.     Add a transaction lifecycle diagram showing the push → poll → webhook sequence with timing.

2.     Document a recommended polling schedule with backoff intervals to prevent rate limit errors.

3.     Create a status reference table that maps processingStatus and queueStatus combinations to their real-world meaning.

4.     Clearly distinguish merchantReference from transactionReference, explain what each is, who generates it, and when to use it.

5.     Document the empty 202 response explicitly, and make clear that merchantReference must be unique and stored client-side before submission.

API Documentation Checklist

Six questions every API documentation should be able to answer clearly:

Question

Moniepoint POS API

For async operations, is there a visual flow and recommended polling schedule?

No, polling is mentioned but no backoff guidance is provided.

Are ambiguous statuses (like Pending or Processing) mapped to a clear state?

No, processingStatus and queueStatus are both present with no explanation of their relationship.

Are duplicate webhook events acknowledged, and is there guidance on handling them?

No, the resend feature confirms duplicates will occur but developers are given no handling instructions.

Are both transaction references explained, and does the doc say when to use each?

No, transactionReference and merchantReference both appear in the response but their distinct roles are never explained.

Does the 202 response document what is (and isn't) returned, and how to retrieve the transaction later?

No, the response body is empty and merchantReference's critical role as the sole transaction handle is not explained.

Conclusion

The Moniepoint POS API is well-built. The gaps identified in this audit are documentation gaps, not product gaps, the underlying system handles async flows, and webhook delivery correctly.

Closing these gaps means developers can integrate with confidence rather than reverse-engineering behaviour through trial and error. Better documentation reduces support overhead, speeds up integration time, and reflects the quality of the product it describes.

The Architecture Audits

Part 2 of 2

Code is the foundation, but clarity is the blueprint. The Architecture Audits is a deep dive into the mental models of the world’s most critical infrastructure, bridging the gap between complex system design and developer experience

Start from the beginning

The Architecture Audits: Why Documentation is the New Blueprint

Mapping the mental models behind the world’s most critical infrastructure.