One payment environment. Many aggregators. Zero rewrites.
Status: 🌱 Pre-release 0.x — core engine, FedaPay and Kkiapay connectors (Benin mobile money). The API may still change. Started on 2026-09-26.
License: Apache 2.0 — free for personal and commercial use, forever.
When you integrate payments, you usually pick one aggregator (FedaPay, Kkiapay, CinetPay, Flutterwave, Paystack, Stripe…). Then reality hits:
- The aggregator is down, and you have no plan B.
- It doesn't support a network your customer uses (a given mobile money operator, a country, a currency) while another aggregator does.
- Another one is cheaper or has a better success rate for that specific route.
- You want to migrate and discover that your whole codebase speaks the old provider's API.
So every team ends up writing, again and again, the same glue code: adapters, fallback logic, dynamic provider selection, webhook normalization, status polling, error mapping. It's hard to get right, and a subtle mistake here means charging a customer twice.
Payenv is an open-source payment orchestration library: a single, stable API in front of many payment aggregators.
// Illustrative only — the API is not final.
const payenv = createPayenv({
connectors: [fedapay({ secretKey }), kkiapay({ ... }), cinetpay({ ... })],
routing: fallback({ order: ['fedapay', 'kkiapay', 'cinetpay'] }),
});
const payment = await payenv.collect({
amount: { value: 5000, currency: 'XOF' },
method: { type: 'mobile_money', network: 'mtn', country: 'BJ', phone: '+22990000000' },
customer: { firstName: 'Ada', lastName: 'Lovelace', email: 'ada@example.com' },
idempotencyKey: 'order_1234',
});
// → Payenv picks a connector that supports MTN / BJ / XOF, tries it,
// and safely falls back to the next one if it fails *before* money moved.What Payenv gives you:
| Capability | What it means |
|---|---|
| Unified API | One request/response model for collections, payouts, refunds and status. |
| Connectors | Pluggable adapters, one per aggregator, all behind the same interface. |
| Capability-aware routing | Only providers that support the country / currency / network / method are considered. |
| Safe fallback | Retries on another provider only when it is proven no money moved. |
| Routing strategies | Priority, weighted, cheapest, best success rate — or your own function. |
| Normalized webhooks | Signature verification per provider, one event format for your app. |
| Normalized statuses & errors | succeeded, failed, pending… and a shared error taxonomy. |
npm install @payenv/core @payenv/connector-fedapayFollow the 5-minute guide, or run the web demo that collects a sandbox payment through FedaPay.
- Library first. Payenv runs inside your app. No hosted service required, no middleman.
- We never touch your money or your keys. Funds flow directly between your customer, the aggregator and you. Credentials stay in your infrastructure.
- Correctness over cleverness. Never double-charge. Ambiguous states are resolved, not guessed.
- No lock-in. Not to a provider — and not to Payenv either.
- No telemetry. Payenv doesn't phone home. Ever.
- Free forever. Apache 2.0, community-governed.
- Getting started — your first payment in 5 minutes
- Vision — why this project exists and where it's going
- Architecture — core concepts: connectors, router, statuses, webhooks
- Connectors — supported and planned aggregators
- Roadmap — milestones
- Decision records — why things are the way they are
- Contributing · Code of Conduct · Security · Governance · Changelog
The project is at its very beginning: this is the best moment to shape it. Ideas, critiques, and knowledge of specific aggregators' quirks are as valuable as code. See CONTRIBUTING.md.
Payenv is not a payment provider, not a bank, and not affiliated with any of the aggregators it connects to. All trademarks belong to their respective owners. Payenv is provided "as is", without warranty — see the LICENSE.
Copyright 2026 The Payenv Authors. Licensed under the Apache License, Version 2.0.