Noria Pay: one payments service across products
2026-09-22 / 4 min / payments / m-pesa / idempotency / infrastructure
Collections, payouts, refunds and statement reconciliation behind one service. Each product keeps its own payment credentials and receives verified settlement events, while the meaning of the money stays in that product.
The payment is shared. Its meaning is not.
A billing product needs to settle an invoice. Another application needs to collect a deposit or pay a supplier. Both need the payment to persist, the provider’s response to be checked and the final outcome to reach the application that asked for it.
Noria Pay is the service I build for that common work. Payment provider integrations, four so far and growing, sit behind collections, payouts, refunds and reconciliation. The available operation depends on the configured payment method; a common interface should not pretend every provider can do the same thing.
The boundary matters. Pay records the movement and reports its outcome. BillGrid, or another calling product, decides which invoice or account that money belongs to. A shared payments service should not become a second place where the customer’s balance is invented.
A project has its own payment identity
A workspace can contain several independent projects. Each project has its own gateway credentials, integration keys, payment links and webhook endpoints.
That separation is more than a label on a transaction list. A payment initiated for one project needs to use that project’s account and notify that project’s application. Giving a developer access to one integration should not quietly give them access to every payment in the workspace.
The dashboard gives operators a place to manage those projects, inspect transactions and follow up on settlement. A public checkout link lets a customer complete a payment without access to the operator’s dashboard.
A retry must mean the same attempt
Money-moving requests require an idempotency key. Replaying the same key and payload returns the original operation; changing the payload under that key is rejected.
The key identifies the attempt, while the caller’s reference says what the payment is for. Those are different jobs. A reference to an invoice is useful for reconciliation, but it is not a reason to forget whether an earlier attempt might already have moved money.
An unknown outcome therefore stays visible as unknown. The caller needs to check and reconcile that operation before treating it as a clean opportunity to charge again.
Confirmation needs recovery as well as callbacks
Providers differ in what their callbacks can prove. Pay checks the evidence behind a payment before it reports success, rather than taking a callback at its word.
A callback can also fail to arrive. Recovery status checks provide another route to the outcome where the payment method supports them. The service keeps uncertainty separate from a confirmed failure, so a timeout does not become a confident answer about money.
Statements are another source of settlement evidence. An import can match deposits to recorded transactions, identify duplicates and leave unmatched or ambiguous entries visible for review. A confirmed reconciliation produces the same kind of outcome event as another confirmation path.
Deliver the result to the product that owns it
An application receives a signed event carrying the transaction, its normalised status and the caller’s reference. Delivery is durable and retried; a destination being unavailable should not stop another product receiving its own events.
The recipient has responsibilities too. Events can be repeated or arrive out of order. The application needs to recognise a transaction it has already credited and keep a later confirmation from being overwritten by an older update.
A successful payment notification is evidence to apply once. It is not an instruction to add the amount again every time the webhook is delivered.
Separate the environments as well as the projects
Sandbox and live traffic have separate credentials and records. Testing an integration must not become an accidental instruction to a production payment account.
The same principle runs through the service: keep the payment identity, the attempt and the evidence distinct. That is what lets several products share the difficult payment work while remaining responsible for their own books.
If you are rebuilding this layer in more than one product, send me a brief. The useful starting point is identifying which payment responsibilities can be shared and which records must stay with the business that owns them.
Read next
- The assistant on this site: a public AI chat with hard limits
A public AI chat that answers only from published writing, streams its replies, keeps spending under a ceiling, and fails in a way the visitor can act on. Small, but it carries every production concern a demo skips.
- SchoolTrack: the learner, the fees and the evidence in one school record
School management for Kenyan schools, connecting learner records, fees, attendance, assessment and guardian access. Built around the people allowed to act on each record, and the evidence behind every change.
