Every request is authenticated with a bearer credential in the Authorization header:
curl 'https://gateway.uk.paayed.com/v1/payments' \
-H 'Authorization: Bearer pyd_secret_live_your_key_here'| Type | Held by | Can do |
|---|---|---|
Secret key (pyd_secret_live_… / pyd_secret_test_…) | Your server only. Never a browser, a mobile app, or a repository. | Everything the granted scopes allow, on behalf of one merchant account. |
Publishable key (pyd_public_live_… / pyd_public_test_…) | Safe to embed in a web page or mobile app. | Exchange card details for a single-use token (hosted fields, coming in a later version). Nothing else. |
Access token (Bearer eyJ...) | A platform acting for many merchants. Minted from a client ID and secret, short-lived. | Whatever the token's scopes allow, against whichever merchant it names. Not yet available — coming in a later version. |
Keys are 48 characters including the prefix. The prefix is part of the credential and is validated, not stripped — a key from another system is rejected outright rather than silently failing somewhere deep.
The key decides the mode. Sandbox and live are two modes of the same account, and you can create keys for either at any time:
account_inactive — build and configure your integration before go-live, and nothing changes on the day.Both modes use the same hostname, gateway.uk.paayed.com. The key alone decides which mode a request runs in, so a sandbox key can never reach real money. Whatever a sandbox key creates is invisible to a live key, and the reverse.
Each mode is activated at the gateway the first time the account uses it, which takes up to a couple of minutes. Activation starts when a key is created, so it is normally finished before your first request. If it is not, the request returns 403 usage_plan_missing: retry after a short wait. It happens once per mode, not once per key, so plan for it on your first live request as well as your first sandbox one.
Every key is scoped. A checkout key that can create payments shouldn't necessarily be able to issue refunds or charge a card off-session.
| Scope | Grants |
|---|---|
payments.read / payments.write | List/retrieve payments; create and confirm 3-D Secure; create, read and expire hosted sessions |
payments.card.raw | Send a card number directly. Requires a PCI attestation on file. |
payments.merchant_initiated | Charge a stored card without the cardholder present |
refunds.read / refunds.write | List/retrieve refunds; create refunds |
customers.read / customers.write | Read and manage customers |
payment_methods.read / payment_methods.write | Read stored cards; write means detaching |
subscriptions.read / subscriptions.write | Read and manage schedules |
events.read | Read the event log |
webhooks.write | Manage webhook endpoints and rotate their secrets |
tokens.create | Publishable keys only: exchange card details for a single-use token |
Roll the key
Roll the key from Developers → API keys in the dashboard, choosing a grace period from one hour to thirty days. A successor key is issued immediately. There is no API for managing keys — a credential that can mint credentials turns one leak into permanent access.
Deploy the new key
Both keys work during the grace period — take your time.
Let the old one expire
Once the grace period ends, the predecessor stops working on its own. No separate revoke step needed.
Revoking a key instead stops it within a second, everywhere. Requests with it are 401 api_key_revoked. If a key leaks, revoke it, then check the dashboard's last-used address and recent calls for that key.
Creating or rolling a live key requires a second-factor challenge in the dashboard, even if your session is already authenticated. Sandbox keys need no step-up. This is a dashboard control, not something your integration needs to handle.
The key is missing, malformed, revoked, or expired. Fails fast, with no I/O — this is the cheapest path in the system for a reason: malformed credentials are the bulk of hostile traffic.
The credential is valid but doesn't carry the scope the route requires. The error body names the missing scope directly.
The environment in the key's prefix and its record disagree. It should not happen; contact support.
The account has not finished activating at the gateway for this mode. This only happens in the first few minutes after an account's first key is created, or after its plan changes. Nothing is wrong with the key: wait a moment and retry. If it lasts more than a few minutes, contact support with the request id.
If the key has an address allow list configured, a request from outside it is rejected and the message names the address that was rejected.
Always accompanied by Retry-After and RateLimit-Reset. RateLimit-Limit and RateLimit-Remaining are on every response, not just on 429s.