Resolving “403 Forbidden” When Creating Payments
Use this guide to troubleshoot 403 errors returned by POST /payments endpoints. A 403 almost always means one or more parts of the payment credential set do not match.
1 – Understand the four-part credential set
Each hosted payment page (terminal entity) is tied to exactly one credential pair and must be addressed with the matching merchant/terminal IDs:
client_id
Provided in your boarding package
Used only to fetch a bearer token for payments
client_secret
Provided with the client_id
Keep private; rotate if compromised
merchantId
Returned in boarding response or portal
Unique to the Volt MS Merchant record
terminalId
Returned in boarding response or portal
Represents the hosted page instance
All four values form an atomic set—mixing values from different sets will result in a 403.
2 – Obtain a bearer token (payments scope only)
Example successful response:
Tokens obtained with these credentials are only for payments; they cannot be used for boarding operations such as creating webhooks, entities, or terminals.
Token-caching rule
Cache the token per credential set. When switching to a different terminal/merchant pair, request a new token—even if the previous one is still valid.
3 – Create a payment
4 – Common 403 causes & fixes
Wrong merchant or terminal ID
Verify IDs against the latest boarding email/portal.
Token generated with mismatched credentials
Ensure client_id
& client_secret
belong to the same terminal/merchant pair used in the payment body.
Re-using a cached token for a different terminal
Always fetch a new token when switching terminals.
Mixing sandbox and production
Sandbox IDs work only on api.test.devs.beadpay.io
; production IDs work only on api.devs.beadpay.io
.
Token expired
Check expires_in
; refresh if older than one hour.
5 – Still blocked?
Confirm the four-part set in a text file—no blanks, no extra spaces.
Call
GET /payments/{trackingId}
with the same token to see if the token is valid at all.Contact developer support with the timestamp, trackingId (if any), and request ID from the 403 response headers.
Last updated