Create subscription
Creates a recurring-payment subscription record tied to a counterparty.
POST/Run in dashboard
The customer must still sign the Solana subscription authorization transaction. The subscriber must be the customer's own wallet: a subscriber that is one of the organization's SDP wallets answers 409, because to pay on a schedule from an SDP wallet you create a recurring payment, which keeps the wallet's token approval bounded.
Requires an API key with the recurring.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
Creates a pending SDP subscription record tied to a counterparty. Lifecycle, schedule, on-chain addresses, and authorization proof are server-owned and populated only by verified flows.
-
planId·string· required · min length 1 · examplepsp_exampleSDP subscription plan ID.
-
counterpartyId·string· required · min length 1 · examplecpty_exampleCounterparty being billed for the recurring payment.
-
subscriberAddress·string· required · example7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsUCustomer wallet address that authorizes the subscription.
Responses
-
201Subscription created-
data·object· requiredSubscription response payload.
-
subscription·object· requiredRecurring payment subscription record.
-
id·string· required · examplepsub_exampleSDP subscription ID.
-
organizationId·string· required · min length 1 · exampleorg_exampleOrganization identifier.
-
projectId·string· required · min length 1 · exampleprj_exampleProject identifier.
-
planId·string· requiredSDP subscription plan ID.
-
counterpartyId·string· requiredCounterparty ID.
-
subscriberAddress·string· required · min length 32 · max length 44 · exampleSo11111111111111111111111111111111111111112Base58-encoded Solana address.
-
subscriberTokenAccount·string | null· required · min length 32 · max length 44 · exampleSo11111111111111111111111111111111111111112Subscriber token account address.
-
subscriptionPda·string | null· required · min length 32 · max length 44 · exampleSo11111111111111111111111111111111111111112On-chain subscription PDA.
-
subscriptionAuthorityAddress·string | null· required · min length 32 · max length 44 · exampleSo11111111111111111111111111111111111111112On-chain subscription authority address.
-
authorizationSignature·string | null· requiredCustomer authorization transaction signature.
-
status·string· required · one ofpending_authorization,active,paused,canceling,canceled,expired· exampleactiveSubscription status.
-
currentPeriodStartAt·string | null· required · formatdate-time· example2025-01-01T00:00:00.000ZISO 8601 timestamp.
-
nextCollectionDueAt·string | null· required · formatdate-time· example2025-01-01T00:00:00.000ZISO 8601 timestamp.
-
cancelAt·string | null· required · formatdate-time· example2025-01-01T00:00:00.000ZISO 8601 timestamp.
-
canceledAt·string | null· required · formatdate-time· example2025-01-01T00:00:00.000ZISO 8601 timestamp.
-
createdBy·string | null· required -
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.
-
-
-
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 therecurring.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.
Example request
curl -X POST 'https://api.solana.com/v1/payments/subscriptions' \
-H "Authorization: Bearer $SDP_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"planId": "psp_example",
"counterpartyId": "cpty_example",
"subscriberAddress": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"
}'Example responses
{
"data": {
"subscription": {
"id": "psub_example",
"organizationId": "org_example",
"projectId": "prj_example",
"planId": "plan_example",
"counterpartyId": "counterparty_example",
"subscriberAddress": "So11111111111111111111111111111111111111112",
"subscriberTokenAccount": "So11111111111111111111111111111111111111112",
"subscriptionPda": "So11111111111111111111111111111111111111112",
"subscriptionAuthorityAddress": "So11111111111111111111111111111111111111112",
"authorizationSignature": "example",
"status": "active",
"currentPeriodStartAt": "2025-01-01T00:00:00.000Z",
"nextCollectionDueAt": "2025-01-01T00:00:00.000Z",
"cancelAt": "2025-01-01T00:00:00.000Z",
"canceledAt": "2025-01-01T00:00:00.000Z",
"createdBy": "example",
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-01T00:00:00.000Z"
}
},
"meta": {
"requestId": "req_example",
"timestamp": "2025-01-01T00:00:00.000Z"
}
}Error responses use the standard error shape.