Resolving “403 Forbidden” When Creating Payments
Use this guide to troubleshoot 403 Forbidden errors returned by Payments endpoints such as POST /payments/crypto.
A 403 usually means your request was authenticated, but the credential you used is not permitted to create a payment for the merchant or terminal in your request.
Related:
401 Unauthorizedusually means the API key is missing or invalid.400 Bad Requestusually means the request body failed validation.
1) Confirm you are using the correct authentication method
Payments use header based authentication with a terminal API key (preferred).
Required headers:
X-Api-Key: {apiKey}Content-Type: application/json
Common mistakes:
Using
Authorization: Bearer ...for Payments (this is legacy and may not work for your credentials)Using the wrong header name (must be exactly
X-Api-Key)Copying a maskedApiKey value instead of the real apiKey value
Example request
curl -s -X POST "https://api.test.devs.beadpay.io/payments/crypto" \
-H "Content-Type: application/json" \
-H "X-Api-Key: {apiKey}" \
-d '{
"merchantId": "{merchantId}",
"terminalId": "{terminalId}",
"requestedAmount": 1.00,
"paymentUrlType": "web",
"reference": "ORDER-123"
}'2) Understand the Payments credential set (API key model)
With API key auth, the credential set is:
apiKey(terminal API key)merchantId(the merchant you are creating a payment for)terminalId(the terminal that will host the payment page)
These values must match the same configured relationship in the environment you are calling. A valid API key used with the wrong merchantId or terminalId is one of the most common causes of 403 Forbidden.
Practical rule:
If you change
terminalId, you should expect to use an API key that is authorized for that terminal.Do not mix IDs across different partners, merchants, or terminals.
3) Confirm you are calling the right environment
Mixing Sandbox and Production values will often produce a 403.
Sandbox base URL:
https://api.test.devs.beadpay.ioProduction base URL:
https://api.devs.beadpay.io
Rules:
Sandbox apiKey works only in Sandbox
Production apiKey works only in Production
Sandbox merchantId and terminalId work only in Sandbox
Production merchantId and terminalId work only in Production
4) Common 403 causes and fixes
Valid apiKey, wrong merchantId
Confirm the merchantId you are sending is the one associated with the terminal credential you were issued
Use the merchantId that matches the terminal key set
Valid apiKey, wrong terminalId
Confirm the terminalId you are sending is the one associated with the apiKey
Use the terminalId that matches the apiKey, or request the correct apiKey for that terminal
Mixing environments
Confirm your base URL and IDs are all for the same environment
Use Sandbox IDs with Sandbox base URL and Production IDs with Production base URL
Terminal not permitted or not enabled
Confirm the terminal is configured for Payments in that environment
Verify terminal configuration with your Bead contact
Request sent with legacy Bearer token
Confirm you are not using Authorization: Bearer ...
Use X-Api-Key for POST /payments/crypto
Caching the wrong credential
Confirm your app is not reusing an apiKey from a different terminal
Store apiKey per terminal and select the correct one at runtime
5) Still blocked?
When escalating a 403, include the following so support can trace the request quickly:
Timestamp (with timezone)
Environment (Sandbox or Production)
Endpoint called (
POST /payments/crypto)merchantId and terminalId you sent
The request ID from response headers (if present)
The full response body (do not include your apiKey)
Tip:
Do not paste the apiKey into tickets or chat. Treat it like a password.
Legacy: 403 troubleshooting for Bearer token integrations
Some existing integrators authenticate Payments using legacy OAuth and send Authorization: Bearer {access_token}. If you are on the legacy model, most 403 issues come from mixing credential sets (for example, token generated for one terminal used with a different terminalId in the request body).
If you believe you are on the legacy model and still seeing 403, confirm with your Bead contact whether your integration should migrate to X-Api-Key authentication for Payments.
Last updated