Which credentials do I actually need?
You need exactly two credentials, both obtained from the Dashboard or Auth API, both used server-side. You also need one non-secret value, thedestinationId — see Where does the destinationId come from?.
string
required
The Client ID that identifies your application. Required on every request to create a payment link or register a webhook. Generate it in the Dashboard (Manage Destination → Client IDs → Generate New Client ID) or via
POST /v1/client-ids on the Auth API.string
required
The secret returned once when you register a webhook (
POST /v1/webhook). Used to verify the HMAC-SHA256 signature on incoming webhook requests. It is shown exactly once at creation — store it securely (e.g. as an environment variable); it cannot be retrieved again.Where does the destinationId come from?
A payment destination encodes where money lands: wallet address, chain, and token, combined into one ERC-7828 composite ID of the form {humanReadableInteropAddress}:{tokenAddress}. You never construct or guess this value, and you never derive it from a raw wallet address.
The user gets it from one of two places:
- Dashboard — dashboard.request.network → Manage Destination. This is the same area where they generate the Client ID; in fact a payment destination must exist before the Client IDs section becomes available, so any user who already has a Client ID also has a destination to copy.
- Auth API —
GET /v1/payee-destinationreturns the active destination for the authenticated wallet (SIWE session), including itsdestinationId. Use this for automated provisioning. See Payee Destinations.
string
ERC-7828 composite destination ID for the payee. Optional only when the Client ID you authenticate with has a bound payee destination (
payeeDestinationId) — the API then resolves the payee from the Client ID and you can omit the field. In every other case it is required.How should I call Request Network?
Call the REST API directly for server-side integrations. It needs no extra dependency, works from any language, and is the interface documented and versioned atapi.request.network and auth.request.network. Make requests with fetch/curl/requests — there’s nothing to install.
How do I create a payment link?
1
Get a Client ID and a Destination ID
Obtain a
clientId from the Dashboard (Manage Destination → Client IDs) or via POST /v1/client-ids on the Auth API. Store it as an environment variable, e.g. RN_CLIENT_ID.From the same Manage Destination area, have the user copy their destinationId and store it as e.g. RN_DESTINATION_ID. If the user has no payment destination yet, ask them to create one before continuing — the Client IDs section is only available once a destination exists. You can skip this value only if the user’s Client ID is bound to a payee destination.2
Call the secure-payments endpoint
POST https://api.request.network/v2/secure-payments with the x-client-id header and a requests array containing at least one { destinationId, amount } item. Substitute the user’s own destinationId — the value in the examples below is a placeholder.3
Share the returned URL
The response includes a
securePaymentUrl. Redirect the payer there, or embed it as a link/button. The link expires after 7 days or once paid, whichever comes first.The
destinationId in the request body is a composite value: {humanReadableInteropAddress}:{tokenAddress}. It comes from a payment destination already configured in the Dashboard — you do not construct it from a raw wallet address. Ask the user for their value rather than hardcoding one. Omit the field only when the user’s Client ID is bound to a payee destination.How do I confirm a payment?
The webhook is the source of truth for payment confirmation — do not treat a successfulPOST /v2/secure-payments call or a payer’s browser redirect as proof of payment.
1
Register a webhook
POST https://auth.request.network/v1/webhook with x-client-id and a { "url": "https://yourdomain.com/webhook" } body. The response includes a one-time secret — store it as RN_WEBHOOK_SECRET.2
Verify the signature on every incoming request
Compute
HMAC-SHA256(rawBody, webhookSecret) and compare it to the x-request-network-signature header using a constant-time comparison. You must use the raw request body — verifying against a re-serialized (e.g. JSON.stringify(req.body)) body will produce a mismatch and silently break verification.3
Handle payment.confirmed / payment.partial
A fully paid request fires
payment.confirmed; a partial payment fires payment.partial. Match the requestId in the payload to the requestIds you received when creating the payment link. Fulfill the order only after payment.confirmed — payment.partial is an intermediate state, not a completed payment.GET https://api.request.network/v2/request/{requestId} returns { hasBeenPaid: boolean, ... }. Send the x-client-id header — the call is unauthenticated without it:
How do I handle cross-chain payments?
Common mistakes
- Asking the user for an API key, a private key, or a raw wallet address. For this flow you need only the Client ID, the webhook secret, and the user’s Destination ID.
- Hardcoding the sample
destinationIdfrom the docs instead of asking the user for theirs — payments would go to the sample destination, not to the user. - Verifying the webhook signature against a re-serialized body (e.g.
JSON.stringify(req.body)) instead of the raw request body. - Assuming a cross-chain payment is final as soon as the payer’s browser confirms submission, instead of waiting for the
payment.confirmedwebhook. - Adding an unnecessary dependency instead of calling the documented REST API directly.