Subscription Checkout
POST
/api/subscriptions/checkoutCreates a subscription checkout session for an existing plan and returns a hosted checkout URL. The customer enters their payment details once, agrees to recurring billing, and NaafiPay charges them automatically on every renewal cycle. Renewals emit subscription.renewed webhooks; if a renewal fails, NaafiPay runs dunning automatically and notifies you via webhook for each attempt. Subscriptions currently support monthly and yearly billing intervals.
Request headers
| Field | Type | Required | Description |
|---|---|---|---|
| Authorization | string | required | Your test or live API key. Example: pg_live_xxx |
| Content-Type | string | required | Must be application/json. Example: application/json |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| plan_id | string | required | The id of a plan you created in the dashboard. Example: plan_pro_monthly |
| customer_email | string | required | Customer email. Used for receipts and portal sign-in. Example: tasin@example.com |
| customer_name | string | required | Customer's full name, shown on receipts. Example: Tasin Fahim |
| success_url | string | required | HTTPS URL after first successful charge. Receives subscription_id as a query param. Example: https://yourapp.com/welcome |
| cancel_url | string | required | HTTPS URL if the customer abandons checkout. Example: https://yourapp.com/pricing |
| metadata | object | optional | Arbitrary key/value pairs returned in webhooks. Max 20 keys. Example: { "user_id": "u_99" } |
Response
200 OK
1{2 "subscription_id": "sub_01HZY8K2R4T8AB7CDEF9G2H3JK",3 "checkout_url": "https://pay.naafipay.com/s/sub_01HZY8K2R4T8AB7CDEF9G2H3JK",4 "status": "incomplete",5 "plan": { "id": "plan_pro_monthly", "amount": 1500, "interval": "month" }6}TipPlans live in the dashboard
Create plans under Dashboard → Subscriptions → Plans. Each plan defines the amount, currency, billing interval, and optional trial period. The plan id you reference here must already exist.
Error codes
| Field | Type | Required | Description |
|---|---|---|---|
| 400 | invalid_plan | optional | plan_id does not exist or belongs to a different storefront. |
| 400 | invalid_url | optional | success_url or cancel_url is not a valid HTTPS URL. |
| 401 | unauthorized | optional | API key is missing or invalid. |
WarningCustomers consent to recurring billing
The hosted checkout shows a clear consent screen for the recurring charge. If you bypass the hosted checkout, you must collect this consent yourself — it is a legal requirement under Bangladesh consumer protection rules.