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 Unauthorized usually means the API key is missing or invalid.

  • 400 Bad Request usually 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.io

  • Production 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

Cause
Check
Fix

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:

  1. Timestamp (with timezone)

  2. Environment (Sandbox or Production)

  3. Endpoint called (POST /payments/crypto)

  4. merchantId and terminalId you sent

  5. The request ID from response headers (if present)

  6. 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