Home
Getting Started

Authentication

Secret keys, publishable keys, and how to rotate credentials without downtime.

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'

Credential types

TypeHeld byCan 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.

Sandbox and live

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:

  • A sandbox key works straight away.
  • A live key is created straight away too, but only authenticates once your account is live. Until then it returns 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.

Scopes

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.

ScopeGrants
payments.read / payments.writeList/retrieve payments; create and confirm 3-D Secure; create, read and expire hosted sessions
payments.card.rawSend a card number directly. Requires a PCI attestation on file.
payments.merchant_initiatedCharge a stored card without the cardholder present
refunds.read / refunds.writeList/retrieve refunds; create refunds
customers.read / customers.writeRead and manage customers
payment_methods.read / payment_methods.writeRead stored cards; write means detaching
subscriptions.read / subscriptions.writeRead and manage schedules
events.readRead the event log
webhooks.writeManage webhook endpoints and rotate their secrets
tokens.createPublishable keys only: exchange card details for a single-use token

Rotation without downtime

1

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.

2

Deploy the new key

Both keys work during the grace period — take your time.

3

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.

Live keys are a step-up action

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.

Error responses

401 authentication_error — missing or invalid credential

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.

403 permission_error — insufficient scope

The credential is valid but doesn't carry the scope the route requires. The error body names the missing scope directly.

403 wrong_environment — key and record disagree

The environment in the key's prefix and its record disagree. It should not happen; contact support.

403 usage_plan_missing — account still activating

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.

403 — source address not allowed

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.

429 rate_limit_error — throttled

Always accompanied by Retry-After and RateLimit-Reset. RateLimit-Limit and RateLimit-Remaining are on every response, not just on 429s.

Built with Sourcey