Create payment request
Creates a payment request: an amount of one token for a payer to send to a custody wallet in the caller's project, through the request's hosted payment link.
POST/Run in dashboard
Requires payment_requests.manage. walletId is the provider wallet ID (walletId from GET /v1/wallets), not the SDP Wallet ID transfers take; an unknown wallet, or one outside the project, returns 404. amount is a decimal string with at most the mint's decimals, so 0.05 and 0.050 are the same request; more decimals return 400. A native SOL request is refused with 409 AMOUNT_BELOW_RENT_MINIMUM when the wallet has no account and the amount is below the rent-exempt minimum. The response is the only one besides GET /v1/payments/requests/{paymentRequestId}/link that carries publicToken. Accepts an Idempotency-Key: a retry with the same key and request returns the original payment request instead of creating a second one.
Requires an API key with the payment_requests.manage action.
Headers
-
x-project-id·string· min length 1 · exampleprj_exampleRequired for dashboard sessions. API keys use their assigned project.
-
Idempotency-Key·stringUse a unique 1–255 printable ASCII key per operation. Reuse it with the same request on retries. An in-flight attempt returns
409; a changed request returns422. Retry and recovery rules.
Request body
application/json · required
Create payment request payload.
-
walletId·string· required · min length 1 · exampleprivy_wallet_123Receiving custody wallet in the caller's project. Provider wallet ID: the
walletIdfield returned by GET /v1/wallets. The wallet recordidand the public key are not accepted. An SDP Wallet ID (cwlt_...) returns 404. -
token·string· required · exampleEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1vMint address of the token to request. Symbols are not accepted; for native SOL, pass
So11111111111111111111111111111111111111112. -
amount·string· required · example10.00Amount to request in UI units, as a decimal string greater than zero with no more decimal places than the mint has.
-
expiresAt·string | null· formatdate-time· defaultnull· example2026-12-01T00:00:00.000ZWhen the request stops accepting payment, as an ISO 8601 timestamp. Null or omitted: it never expires.
Responses
-
201Payment request created-
data·object· requiredA new payment request, with its link token.
-
id·string· required · examplepreq_exampleSDP payment request ID.
-
organizationId·string· requiredOrganization ID.
-
projectId·string | null· requiredProject ID.
-
walletId·string· requiredReceiving custody wallet's provider ID.
-
destinationAddress·string· required · min length 32 · max length 44 · exampleSo11111111111111111111111111111111111111112Address the payment is sent to.
-
token·string· requiredToken mint address.
-
amount·string· required · example100.00Token amount in UI units (decimal string).
-
reference·string· required · min length 32 · max length 44 · exampleSo11111111111111111111111111111111111111112Solana Pay reference account that identifies the payment on chain.
-
status·string· required · one ofawaiting_payment,paid,canceled,expired· examplecanceledPayment request status.
awaiting_paymentis open;paidwas settled by an on-chain payment;canceledandexpiredclosed without one. -
expiresAt·string | null· required · formatdate-time· example2025-01-01T00:00:00.000ZExpiry, if any.
-
fulfilledByTransferId·string | null· requiredThe inbound transfer that paid the request.
-
paidLate·boolean· requiredWhether the payment landed after the request expired or was canceled. A payer who signed before then can still pay.
-
lastCheckedAt·string | null· required · formatdate-time· example2025-01-01T00:00:00.000ZWhen SDP last read the chain for the payment.
-
canceledByApiKeyId·string | null· requiredThe API key that canceled the request; null when a member did, or it is not canceled.
-
canceledByUserId·string | null· requiredUser ID of the member who canceled the request; null when an API key did, or it is not canceled.
-
canceledAt·string | null· required · formatdate-time· example2025-01-01T00:00:00.000ZWhen it was canceled.
-
lifecycle·object[]· requiredEvery status the request entered, oldest first.
-
status·string· required · one ofawaiting_payment,paid,canceled,expired· examplecanceledPayment request status.
awaiting_paymentis open;paidwas settled by an on-chain payment;canceledandexpiredclosed without one. -
at·string· required · formatdate-time· example2025-01-01T00:00:00.000ZISO 8601 timestamp.
-
-
createdBy·string | null· requiredUser ID of the member, or of the API key's creator, who created it.
-
createdAt·string· required · formatdate-time· example2025-01-01T00:00:00.000ZISO 8601 timestamp.
-
updatedAt·string· required · formatdate-time· example2025-01-01T00:00:00.000ZISO 8601 timestamp.
-
publicToken·string· required · exampleexample-public-tokenToken behind the request's hosted payment link,
/pay/{publicToken}. Anyone holding it can build the request's fee-sponsored payment transaction, so share it only with the payer. Reads never return it; get it again withGET /v1/payments/requests/{paymentRequestId}/link.
-
-
meta·object· requiredResponse metadata.
-
requestId·string· required · min length 1 · examplereq_exampleRequest identifier for tracing.
-
timestamp·string· required · formatdate-time· example2025-01-01T00:00:00.000ZISO 8601 timestamp.
-
-
-
400Bad Request-
error·object· requiredStandard error payload.
-
code·string· requiredMachine-readable error code.
-
message·string· requiredHuman-readable error message.
-
details·objectOptional error details for debugging.
*·any
-
-
meta·object-
requestId·string· min length 1 · examplereq_exampleRequest identifier for tracing.
-
-
-
401UnauthorizedSame fields as
400. -
403Forbidden. Requires thepayment_requests.manageaction: an API key must hold it (a module'smanageorexecutealso covers itsread), and a signed-in member's organization role must include it. Without it the error is INSUFFICIENT_PERMISSIONS anderror.details.actionnames the action. Any other 403 names its own reason.Same fields as
400. -
404Not FoundSame fields as
400. -
409ConflictSame fields as
400. -
422Unprocessable EntitySame fields as
400. -
500Internal Server ErrorSame fields as
400. -
503Service UnavailableSame fields as
400.
Example request
IDEMPOTENCY_KEY=$(uuidgen)
curl -X POST 'https://api.solana.com/v1/payments/requests' \
-H "Authorization: Bearer $SDP_API_KEY" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-H "Content-Type: application/json" \
-d '{
"walletId": "privy_wallet_123",
"token": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"amount": "10.00",
"expiresAt": null
}'Example responses
{
"data": {
"id": "preq_example",
"organizationId": "organization_example",
"projectId": "project_example",
"walletId": "wallet_example",
"destinationAddress": "So11111111111111111111111111111111111111112",
"token": "example",
"amount": "100.00",
"reference": "So11111111111111111111111111111111111111112",
"status": "canceled",
"expiresAt": "2025-01-01T00:00:00.000Z",
"fulfilledByTransferId": "fulfilledbytransfer_example",
"paidLate": false,
"lastCheckedAt": "2025-01-01T00:00:00.000Z",
"canceledByApiKeyId": "canceledbyapikey_example",
"canceledByUserId": "canceledbyuser_example",
"canceledAt": "2025-01-01T00:00:00.000Z",
"lifecycle": [
{
"status": "canceled",
"at": "2025-01-01T00:00:00.000Z"
}
],
"createdBy": "example",
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-01T00:00:00.000Z",
"publicToken": "example-public-token"
},
"meta": {
"requestId": "req_example",
"timestamp": "2025-01-01T00:00:00.000Z"
}
}Error responses use the standard error shape.