Create Payment

Create a payment with POST /Payments/crypto to generate one or more hosted payment URLs. The hosted payment page handles the checkout experience for supported crypto and digital wallet tenders. Optional tender preselection is available for advanced integrations that want to direct the shopper into a specific tender flow or a curated tender subset, but it is not required.

Overview

  • Endpoint: POST /Payments/crypto Sandbox base: https://api.test.devs.beadpay.io

  • Supports crypto and digital wallet tenders

  • Returns one or more hosted payment URLs you can embed or open

  • Optionally redirects the shopper to redirectUrl

  • Supports optional per-payment webhooks via webhookUrls, in addition to the terminal’s default webhook

For an end-to-end Sandbox flow, see Quick Start.

Step 1: Authenticate

Payments use header-based authentication with a terminal API key.

The terminal API key is the secret credential used to authenticate requests. The masked API key is a display value only and cannot be used to authenticate.

Required headers

X-Api-Key: {apiKey}
Content-Type: application/json
Accept: application/json

Authentication guidance

  • Preferred for new integrations: use X-Api-Key

  • Supported for existing legacy Payments integrations: OAuth password grant with Authorization: Bearer {access_token}

  • Do not place the API key in the request body or URL

  • Do not expose the API key in browser or mobile client code

See Authentication for full token and legacy OAuth details.

Step 2: Create a hosted payment URL

Send a request to create a payment. The response includes trackingId, paymentPageId, and paymentUrls.

Endpoint

Headers

Request shape guidance

Required fields can vary depending on terminal configuration, terminal type, and tender-specific requirements.

At a minimum, all payment creation requests should include:

  • terminalId

  • merchantId

  • requestedAmount

Other common fields include:

  • reference

  • description

  • redirectUrl

  • emailReceipt

  • smsReceipt

  • refundEmail

  • webhookUrls

  • customer

Minimum payment amounts

Minimum payment amounts can vary by tender.

For USDC on Base and USDC on Solana, the minimum Bead payment amount is $1.00 USD. If a payment request is limited to either of these tenders, or if the hosted payment experience is expected to present either of these tenders as an available option, use a requestedAmount of 1.00 or higher.

This minimum is separate from any network fee the payer’s wallet may require to submit the transaction.

Terminal type considerations

For some payment flows, required fields differ depending on the terminal type.

Terminal type = virtual

For flows such as Klarna testing, terminals with type = virtual may require:

  • merchantId

  • terminalId

  • requestedAmount

  • refundEmail

  • customer

Terminal type = physical

For flows such as Klarna testing, terminals with type = physical may require:

  • merchantId

  • terminalId

  • requestedAmount

  • customer

Important note

The exact minimum request body is not universal across all tenders and terminal setups.

Examples:

  • some payment flows only require the basic payment fields

  • some flows require the full customer object

  • some flows require refundEmail, especially for terminals with type = virtual

  • terminals with type = physical may allow a different minimum request shape

When documenting or testing a specific tender, use a request example that matches that tender and terminal type.

Example request body: basic

Use this as a basic hosted payment example. It is not a guaranteed universal minimum for every payment flow.

Example request body for terminal type = virtual

This example is appropriate for flows that require customer details and refundEmail, such as certain digital wallet or Klarna-related scenarios.

Example request body for terminal type = physical

This example is appropriate for flows that require customer details but do not require refundEmail.

Example request body: expanded

Notes

  • refundEmail is recommended when you have a payer email available. It is used to send reclaim instructions if the payment ends as underpaid, overpaid, expired, invalid, or cancelled.

  • The customer object may be required depending on terminal configuration and tender flow.

  • If you include the customer object, provide all required customer fields.

Example response

Key fields

  • terminalId — Terminal identifier in Bead. Determines device-level settings such as tender configuration and terminal default webhook.

  • merchantId — Merchant identifier. Used for reporting and settlement.

  • requestedAmount — Amount in the requested currency. For USDC on Base and USDC on Solana, use 1.00 or higher.

  • tenderTypes — Optional array used to limit the payment to specific tenders. When you limit a payment to USDC on Base or USDC on Solana, the requestedAmount must be at least 1.00.

  • reference — Merchant-side reference such as an order or invoice number.

  • description — Description that may be shown to the customer and in reporting.

  • customer — Customer object when required by the payment flow.

  • redirectUrl — Optional URL Bead redirects to after checkout completes or is cancelled.

  • emailReceipt, smsReceipt — Optional receipt delivery settings.

  • refundEmail — Optional email used for reclaim instructions when unconverted crypto must be returned to the payer.

  • webhookUrls — Optional array of additional webhook endpoints for this payment.

Underpayments and overpayments

In wallet-based crypto payments, the customer typically scans a QR code to set the destination and then manually enters the amount in their wallet app. If they mistype the amount, the payment can end in one of these outcomes:

  • underpaid — The customer sent less than requested

  • overpaid — The customer sent more than requested

Recommended handling

  • Underpaid: treat as unsuccessful. Do not fulfill. If the customer still wants to pay, create a new payment and start a new hosted checkout.

  • Overpaid: treat as successful for the requested amount. You may fulfill once confirmed. The overage is returned to the payer through the reclaim flow.

Email behavior for reclaim

  • If you provide refundEmail, Bead emails reclaim instructions when reclaim is required.

  • If refundEmail is not provided, the hosted payment page prompts the payer to enter an email address when an underpaid or overpaid outcome occurs, then Bead emails reclaim instructions.

Webhooks

If you include webhookUrls, Bead sends payment lifecycle events to both:

  1. the terminal’s default webhook

  2. each URL in the webhookUrls array

Configure at least one webhook endpoint before you depend on webhooks in production. See Payment Webhooks for payload and retry details.

Customer data rule

If your payment flow requires a customer object, include all required customer fields.

Typical required fields are:

  • firstName

  • lastName

  • email

  • address

  • address2

  • city

  • state

  • postalCode

  • countryCode

If you send a partial customer object, the API may return 400 Bad Request with validation errors.

Step 3: Present the hosted page

Use the first URL in paymentUrls to start checkout.

Common patterns

  • Web or SPA: embed the URL in an iframe or open a new tab or window

  • Native app: load the URL in an in-app browser or webview

Redirect behavior

  • If redirectUrl is provided, Bead redirects the browser to redirectUrl after success or cancel and includes context in the query string.

  • If redirectUrl is not provided, Bead displays a hosted confirmation page that indicates success or cancellation.

Regardless of redirect choice, always confirm the final status via webhooks or status polling before shipping goods or granting access.

Step 4: Confirm payment status

You can confirm payment status using webhooks or polling.

Option A: Webhooks

  • Configure a terminal-level webhook and optionally supply webhookUrls per payment

  • Your server receives JSON payloads whenever statusCode changes

  • Respond with 200 OK as soon as you have persisted or queued the event

Option B: Polling

Endpoint:

Headers:

Example curl:

Use the trackingId returned from the Create Payment response.

Typical statuses

  • created and processing while the customer is paying

  • completed when the payment has fully succeeded

  • underpaid, overpaid, expired, invalid, or cancelled for non-happy-path outcomes

For full status details, see Payment Statuses.

Troubleshooting

  • 401 Unauthorized

    • API key is missing, invalid, or sent using the wrong header name. The header must be exactly X-Api-Key.

  • Hosted page will not load

    • Confirm you are using a URL from the paymentUrls array returned by the create payment response.

    • Confirm the terminal is configured for at least one tender in the environment you are testing.

  • Validation error on payment creation

    • Confirm you are using a request shape that matches the terminal type and tender requirements.

    • If testing USDC on Base or USDC on Solana, confirm requestedAmount is at least 1.00.

    • If using tenderTypes, confirm the selected tenders are enabled for the terminal and merchant.

    • If using a terminal with type = virtual, confirm whether refundEmail is required for the flow you are testing.

    • If using a flow that requires customer, confirm that all required customer fields are present.

  • No status change

    • Confirm you are polling the correct trackingId.

    • If using webhooks, confirm your endpoint is reachable and returns HTTP 200 quickly.

Next steps

After you can create and complete a payment in Sandbox:

  • Configure Payment Webhooks and verify your endpoint receives status events

  • Use Payment Statuses for ad hoc queries and troubleshooting

  • Explore Reporting and Settlement to build payment history and reconciliation jobs

  • When ready for Production, request production credentials and switch API base URLs to Production

Legacy authentication

Some existing integrations authenticate Payments using OAuth 2.0 password grant with a terminal username and password. New Payments integrations should use the terminal API key method described above.

If you are using legacy OAuth for Payments, obtain an access token using the password grant and send:

See the Authentication page for token endpoint details, realms, and refresh token usage.

Last updated