Developers

A payments API for the Maldives

Take payments, hold funds, read balances, over REST, against a ledger we built ourselves.

Create a checkout session
curl https://api.payer.app/checkout/sessions \
  -H "Authorization: Bearer sk_live_..." \
  -H "Idempotency-Key: order_10482" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 24900,
    "title": "Order #10482",
    "reference": "order_10482"
  }'
Response
{
  "id": "9b1c8f2e-3d4a-4f11-a0c2-...",
  "reference": "order_10482",
  "url": "<hosted checkout link>"
}

The API surface

Everything we have, and everything we don't.

Checkout sessionsLive
Create, retrieve, cancel. Hosted checkout page per session.
BalancesLive
Read wallet balances, derived from ledger entries.
HoldsLive
Reserve funds, then settle or release. Distinct ledger states.
Keys and scopesLive
Live and test keys. Issue, rotate, revoke. Every change audited.
SandboxLive
Separate environment, own keys and accounts. Toggled from the dashboard.
WebhooksBuilding
Signed payloads, event catalogue, delivery logs, manual replay.
API reference and JS SDKBuilding
Generated from one OpenAPI spec.
Payment linksPlanned
Hosted, no code required.
Payouts and refundsPlanned
Behind the scope catalogue that already exists.
Personal access tokensPlanned
Read your own account. Writes need a confirmation on your phone.
OAuthPlanned
Consent screens for third-party apps.
MandatesDesign
Scoped, time-bound delegated authority for agents.

Underneath it is a payment service provider licensed by the Central Bank of Maldives under the National Payment System Act, with customer funds in a segregated account. The compliance obligations are ours.

Behaviour worth knowing about

Four decisions that will affect how you write the integration.

Keys carry their environment
sk_test_ can't reach production, and pk_live_ won't be mistaken for a test key in a log. Secrets are shown once, stored hashed, and rotate without downtime. Issues, rotations and revocations are all audited.
Every write is safe to retry
Send an Idempotency-Key on any mutating call. A repeat of the same key replays the original response instead of charging twice. The same key with a different body returns 409. Keys are scoped to the credential that used them.
The sandbox is a real deployment
A separate environment running the same code, with its own accounts and keys, rather than a flag that takes a different branch in process. The path you test is the path that runs in production.
Scopes and per-key limits
A key that only creates checkout sessions can't read balances or move money. Rate limits are per key, so one noisy integration doesn't throttle the rest of your account.

Credentials

One scope catalogue, several kinds of caller. A scope means the same thing whoever holds the credential, and every grant and revocation lands in the same audit trail.

CredentialWho holds itWhat it can doStatus
pk_Merchant, client-sideCreate-only. Safe to ship in a browser or an app bundle.Live
sk_Merchant, server-sideFull merchant scope, bounded by the scopes you grant the key.Live
pat_An individual, on their own accountRead your own balances and transactions. Moving money needs a step-up on your phone.Design
oauthA third-party app, on behalf of someoneWhatever the user granted on the consent screen, and nothing else.Design
mandateAn agent, delegatedScoped, time-bound, revocable at any moment by the person who granted it.Design

The last three don't exist yet. They're here so you can see the shape of the model, not so you can plan against them.

Toward programmable money

A payments API moves money when you tell it to. We're building toward money you can attach conditions to: funds that release when something becomes true, authority that expires on its own, limits the ledger enforces instead of your application code.

Holds are the part of this that already works. Money sits under conditional control and settles or releases later, as a real ledger state rather than a flag your code has to remember to check. We can offer that because the ledger is ours: conditions on money have to be enforced where the money is, not in a layer above someone else's core.

Mandates are the next piece. Authority scoped to a purpose, capped, expiring, revocable in one tap, for software that spends on a person's behalf. The agent proposes a payment; the person confirms it on their phone against the exact amount and payee; the ledger records which mandate it happened under. An agent that misbehaves burns its own authority, not the account.

That's the direction, not a date. If it's why you're here, say so below.

Get access

Tell us what you're building. We onboard in small batches, so you'll get answers from someone who worked on the endpoint.

We'll only use this to contact you about API access. See our privacy policy.