On this page
API Keys
Create Payment or Payout API keys, understand their scopes and prefixes, rotate credentials safely, and separate test from live access.
Paymos issues two key types per environment, each scoped to a fixed set of operations. A leaked Payment credential cannot move funds — scope is checked centrally on every request, so a Payment key can never reach a payout endpoint no matter which route it hits.
Key types
| Type | Prefix | Scope |
|---|---|---|
| Payment | pk_ |
Create invoices, read invoice status, manage payment channels and read their deposits |
| Payout | rk_ |
Create withdrawals, cancel withdrawals, read balances |
API secrets use the sk_ prefix. Webhook signing secrets use whsec_.
Environments
Every credential is tied to one environment. The environment is encoded in the prefix:
| Environment | Prefix modifier | Example |
|---|---|---|
| Production | _live_ |
pk_live_…, rk_live_… |
| Sandbox | _test_ |
pk_test_…, rk_test_… |
A fully-configured merchant holds four API key IDs (pk_live_…, pk_test_…, rk_live_…, rk_test_…) and two webhook secrets (whsec_live_…, whsec_test_…).
Scope details
The scope split is enforced centrally, not per route: the access level is derived from the key type on every request, so a Payment key reaches only money-in endpoints and a Payout key only payout endpoints.
Payment channels sit on the money-in side. All eight channel and deposit routes require a Payment key and answer 403 payment_key_required to a Payout key — the mirror image of withdrawals rejecting a Payment key.
Reading balances is the split that surprises people: GET /v1/balances needs a Payout key. The Payment key is the one that lives on shop servers, ships with every deployment and turns up in the widest blast radius, so it is not given a view of what you are holding. Read balances from the same place you initiate payouts.
A Payout credential can also carry an IP whitelist, set in the dashboard. While your withdrawal whitelist is on, it is optional. With entries on it, a call from any address outside the list is refused with ip_not_allowed; left empty, the key is callable from anywhere, which is what a serverless function or any host without a fixed outbound IP needs. A Payment key cannot carry one at all.
An owner who has had the withdrawal whitelist switched off through support loses that choice on the live Payout key. Payouts from it are refused with ip_allowlist_required until it lists at least one IP, and the last entry cannot be removed until the whitelist is back on.
A Payout key can move funds out of your Paymos balance — treat it like your bank password. With the withdrawal whitelist on, which is the default, it cannot pick a new destination: a withdrawal goes only to an address already on the whitelist, and that list changes only in the dashboard, with a fresh second-factor confirmation when one is enrolled. Once the whitelist is off, the key can pay any address, and its IP whitelist is all that stops it working from someone else's server. If your servers do have fixed IPs, put them on the key's IP whitelist and keep it narrow.
Lifecycle
| Status | Description |
|---|---|
| Active | Credential is operational and accepts requests |
| Revoked | Terminal state. Credential is permanently disabled and cannot be reactivated |
Security best practices
- —Never expose API secrets in client-side code
- —Rotate secrets periodically via the dashboard — a grace period keeps the previous secret valid during transition
- —Use separate credentials for production and sandbox
- —Restrict Payout credentials by IP address where your servers have fixed ones — and always, if your withdrawal whitelist is off
- —Store API secrets only in environment variables or a secrets manager
See Authentication for the HMAC-SHA256 signing scheme that uses these credentials.