Skip to content

Buy a one-time SMS credit pack without leaving the app.

POST
/billing/sms-credits/purchase
curl --request POST \
--url https://api.siteqwality.com/billing/sms-credits/purchase \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "pack_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "idempotency_key": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" }'

The in-app replacement for POST /billing/sms-credits/checkout. It creates a PaymentIntent rather than redirecting to Stripe’s hosted page, so the card is collected by the Payment Element on our own Billing tab and the PAN never touches our servers.

Nothing is credited here. The response is only a client secret; the balance moves when the payment_intent.succeeded webhook arrives, which is what keeps a customer who closes the tab mid-payment from being charged without credits or credited without paying.

Media type application/json
object
pack_id
required
string format: uuid
idempotency_key
required

Client-generated, stable across retries of ONE confirm attempt. Same contract as POST /billing/addons: the same value twice is one charge.

string format: uuid
Example generated
{
"pack_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"idempotency_key": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"
}

PaymentIntent client secret

Media type application/json
object
client_secret
required

Hand this to Stripe’s Payment Element to collect and confirm the card. The credits land when payment_intent.succeeded arrives, never here.

string
Example generated
{
"client_secret": "example"
}

Unknown or inactive pack, or the card was declined

Missing or invalid authentication

Caller is not a super admin, or the account has no paid plan

Account has no Stripe customer

Internal server error