Subscriptions
Create Request
Request to create a subscription that bills a customer on a recurring schedule. On each billing date the customer's vaulted card(s) are charged automatically — the default card is attempted first, cascading through the remaining active cards in priority order (see Card Vault Charge). Pass card_id to bill a specific card only (no cascade).
Recurring charges are processed as merchant-initiated transactions (MIT) — no 3DS challenge is presented. The 3DS authentication from the original card storage (see Card Vault Link) provides the authentication reference for scheme compliance. The customer must therefore have at least one ACTIVE vaulted card, unless collection_method is REQUEST_PAYMENT.
Line items come from your product catalog — see products. Pass a single items array; each product's pricing type determines how it is stored and billed: RECURRING products bill on every cycle, while ONE_TIME products (e.g. a setup fee) are billed on the first cycle only.
The billing schedule is determined by the products. Each recurring product carries its own billing interval (e.g. monthly, yearly, or a custom interval such as every 6 weeks), which populates the subscription's billing.period — and billing.custom_interval / billing.custom_period for custom intervals. You do not pass a period on the request; all RECURRING products in one subscription must share the same billing interval, otherwise the request is rejected.
Path
POST /subscriptions/{customer_id}
| Path Parameter | Type | Description | Example |
|---|---|---|---|
| customer_id | String(32) | The customer to subscribe — see customers | cus_abc123... |
Example (Basic)
Basic example of a subscription starting today. The billing period comes from the product — a monthly product bills monthly. The customer's default card is charged on each billing date, cascading through fallback cards on decline.
{
"items": [
{
"product_id": "pro_abc123...", // RECURRING catalog product; its interval sets the billing period
"qty": 1 // default 1 when omitted
}
],
"reference": "SUB-2026-00042" // your reference; appears on statements and reporting
}
Example (Trial and setup fee)
Start with a 14-day trial. The ONE_TIME setup fee product is automatically billed on the first cycle only, together with the first recurring cycle when the trial ends.
{
"items": [
{
"product_id": "pro_abc123...", // RECURRING — billed every cycle
"qty": 1
},
{
"product_id": "pro_setup1..." // ONE_TIME — billed on the first cycle only
}
],
"trial_days": 14, // subscription starts in TRIAL; first charge when the trial ends
"reference": "SUB-2026-00042"
}
Example (Advanced)
Advanced example with all options, including billing anchoring, invoicing, cascade controls, and a fixed end date.
{
"items": [
{
"product_id": "pro_abc123...",
"qty": 2 // default 1 when omitted
},
{
"product_id": "pro_xyz789...",
"price_excl": 300.23 // override the default product amount
},
{
"product_id": "pro_setup1..." // ONE_TIME product — billed on the first cycle only
}
],
"currency": "ZAR", // [optional] default "ZAR"
"reference": "SUB-2026-00042", // your reference; appears on statements and reporting
"signature": "secret-key-for-payload", // [optional] shared-secret signature for the payload, see the signature section below
// Billing schedule — the period itself comes from the recurring product's interval and cannot be set here
"billing": {
"billing_day": 1, // [optional] anchor day of the month (1–31) for MONTHLY and longer periods; defaults to the day of date_start
"date_start": "2026-08-01", // [optional] default today; first billing date (after any trial)
"date_end": "2027-07-31" // [optional] subscription expires after this date; omit to run until cancelled
},
"trial_days": 14, // [optional] trial period before the first charge
"collection_method": "AUTOCHARGE", // [optional] default AUTOCHARGE — charge the vaulted card(s); REQUEST_PAYMENT sends the customer a payment request instead
"due_days": 7, // [optional] REQUEST_PAYMENT only — days after each billing date before the payment request is overdue
"card_id": "crd_SFq2E9LskQimPkf2mRqnV", // [optional] bill this card only; the cascade is disabled. Omit to use the default card with cascade
// Cascade behaviour on each billing date — ignored when card_id is passed
"cascade": {
"is_enabled": true, // [optional] default true — when false, only the default card is attempted
"max_attempts": 3, // [optional] cap on the number of cards tried; defaults to all ACTIVE cards
"skip_codes": ["DO_NOT_HONOUR"] // [optional] additional decline codes that abort the cascade; hard declines (e.g. SUSPECTED_FRAUD, STOLEN_CARD, PICKUP_CARD) always abort and cannot be overridden
},
"is_tax": true, // [optional] default true — apply tax to line items
// Issue and optionally email an invoice on each billing cycle
"invoice": {
"is_generate": true,
"is_send": true, // email each invoice to the customer when true
"memo": "Thank you for subscribing", // [optional] shown above the invoice lines
"footer": "VAT No. 4123456789" // [optional] shown below the invoice lines
},
"notification": {
"email": "me@my-email.co.za", // [optional] email notification on subscription lifecycle events
"webhook_url": "https://merchant.example/webhooks/subscriptions" // webhook on subscription lifecycle events
},
"metadata": {
"order_id": "ord_98765" // [optional] custom key/value pairs returned on the subscription and webhooks
}
}
Request Parameters
Fields below appear in the request body examples on this page. Y = required for all requests, C = required or applicable depending on usage.
Field | Required | Type | Description | Example |
|---|---|---|---|---|
| items | Y | Array | Line items from your catalog. Each product's pricing type determines how it is billed: RECURRING products bill on every cycle, ONE_TIME products on the first cycle only. At least one RECURRING product is required, and all RECURRING products must share the same billing interval — see products | See basic example |
| items.product_id | Y | String | Catalog product for this line | pro_abc123... |
| items.qty | N | Integer | Quantity for this line item (default 1) | 2 |
| items.price_excl | N | Number | Override the default product amount (excluding tax) | 300.23 |
| billing.billing_day | N | Integer | Anchor day of the month (1–31) for MONTHLY and longer periods; months with fewer days bill on the last day. Defaults to the day of date_start. The billing period itself is derived from the recurring product's interval and cannot be set here | 1 |
| billing.date_start | N | String | First billing date (YYYY-MM-DD), after any trial. Default today | 2026-08-01 |
| billing.date_end | N | String | Date after which the subscription expires with status EXPIRED. Omit to run until cancelled | 2027-07-31 |
| trial_days | N | Integer | Trial period in days before the first charge; the subscription starts in TRIAL | 14 |
| collection_method | N | ENUM | AUTOCHARGE (default) charges the vaulted card(s) on each billing date; REQUEST_PAYMENT emails the customer a payment request instead, see lookups | AUTOCHARGE |
| due_days | C | Integer | REQUEST_PAYMENT only — days after each billing date before the payment request is overdue | 7 |
| card_id | C | String(32) | Bill this specific card only; the cascade is disabled. Omit to bill the default card with cascade | crd_SFq2E9LskQimPkf2mRqnV |
| cascade | N | Object | Cascade behaviour on each billing date; ignored when card_id is passed — see Card Vault Charge | See advanced example |
| cascade.is_enabled | N | Boolean | When false, only the default card is attempted. Default true | true |
| cascade.max_attempts | N | Integer | Cap on the number of cards tried; defaults to all ACTIVE cards | 3 |
| cascade.skip_codes | N | Array | Additional decline codes that abort the cascade instead of trying the next card. Hard declines (SUSPECTED_FRAUD, STOLEN_CARD, PICKUP_CARD) always abort and cannot be overridden — see lookups | [DO_NOT_HONOUR] |
| currency | N | String(3) | ISO 4217 currency code. Default ZAR | ZAR |
| reference | Y | String(35) | Your reference for this subscription; appears on statements and reporting | SUB-2026-00042 |
| is_tax | N | Boolean | Apply tax to line items. Default true | true |
| signature | N | String | Optional passphrase signature for verifying the payload | secret-key-for-payload |
| invoice.is_generate | N | Boolean | Whether to generate an invoice on each billing cycle | true |
| invoice.is_send | N | Boolean | Whether to email each invoice to the customer | true |
| invoice.memo | N | String | Memo shown above the invoice lines | Thank you for subscribing |
| invoice.footer | N | String | Footer shown below the invoice lines | VAT No. 4123456789 |
| notification.email | N | String | Email address to notify on subscription lifecycle events | me@my-email.co.za |
| notification.webhook_url | N | String | Webhook URL for subscription lifecycle events | https://merchant.example/webhooks/subscriptions |
| metadata | N | Object | Custom key/value metadata returned on the subscription and webhooks | {"order_id": "ord_98765"} |
Response Body
A subscription (sub_) is returned with its resolved billing schedule and totals. The items array you passed is split by each product's pricing type: RECURRING products are stored under items and ONE_TIME products under items_one_time. The recurring product's interval populates billing.period — and billing.custom_interval / billing.custom_period when the product bills on a custom interval.
Each billing cycle produces a charge on the customer's card(s) — the latest outcome is reflected in last_transaction_id and last_invoice_id.
{
"status": true,
"result": {
"id": "sub_Wt5RmK2xPqLv9nYcE7aBz",
"customer_id": "cus_abc123...",
"reference": "SUB-2026-00042",
"subscription_status": "TRIAL",
"collection_method": "AUTOCHARGE",
"card_id": null,
"items": [
{
"product_id": "pro_abc123...",
"qty": 2,
"price_excl": 300.23
}
],
"items_one_time": [
{
"product_id": "pro_setup1...",
"qty": 1
}
],
"billing": {
"period": "MONTHLY",
"billing_day": 1,
"date_start": "2026-08-01",
"date_end": "2027-07-31"
},
"trial_days": 14,
"total_recurring_excl": "600.46",
"total_recurring_incl": "690.53",
"total_one_time_excl": "150.00",
"total_one_time_incl": "172.50",
"currency": "ZAR",
"date_next_billing": "2026-08-01",
"date_last_billing": null,
"last_transaction_id": null,
"last_invoice_id": null,
"created_at": "2026-07-06T10:15:30Z"
}
}
Response Parameters
Field | Type | Description | Example |
|---|---|---|---|
| status | Boolean | Whether the request succeeded | true |
| result.id | String(32) | Unique subscription identifier | sub_Wt5RmK2xPqLv9nYcE7aBz |
| result.customer_id | String(32) | Associated customer ID | cus_abc123... |
| result.reference | String(35) | Your reference for this subscription | SUB-2026-00042 |
| result.subscription_status | ENUM | Subscription state: TRIAL, ACTIVE, PAUSED, CANCELLED, EXPIRED, FAILED, or DISABLED, see lookups | TRIAL |
| result.collection_method | ENUM | How each cycle is collected, see lookups | AUTOCHARGE |
| result.card_id | String(32) | The specific card billed each cycle; null when using the default card with cascade | crd_SFq2E9LskQimPkf2mRqnV |
| result.items | Array | RECURRING line items, billed on every cycle | ... |
| result.items_one_time | Array | ONE_TIME line items, billed on the first cycle only | ... |
| result.billing | Object | Resolved billing schedule. period is populated from the recurring product's interval; custom_interval and custom_period are included when the product bills on a custom interval, see lookups | See response body |
| result.trial_days | Integer | Trial period in days; null when no trial | 14 |
| result.total_recurring_excl | String | Recurring total per cycle, excluding tax | 600.46 |
| result.total_recurring_incl | String | Recurring total per cycle, including tax | 690.53 |
| result.total_one_time_excl | String | One-time total billed on the first cycle, excluding tax | 150.00 |
| result.total_one_time_incl | String | One-time total billed on the first cycle, including tax | 172.50 |
| result.currency | String(3) | ISO 4217 currency code | ZAR |
| result.date_next_billing | String | Next billing date | 2026-08-01 |
| result.date_last_billing | String | Most recent billing date; null before the first cycle | 2026-08-01 |
| result.last_transaction_id | String(32) | Transaction from the most recent billing cycle; null before the first cycle | tra_pr6CvR_4pvWwmgQ4y3dtY |
| result.last_invoice_id | String(32) | Invoice from the most recent billing cycle; null before the first cycle or when invoicing is disabled | inv_k2Jd8sLqPz... |
| result.created_at | String | ISO timestamp when the subscription was created | 2026-07-06T10:15:30Z |
Change Plan Request
Change the recurring line items of a subscription. As on create, the billing period is determined by the products — passing products with a different interval (e.g. moving from monthly to yearly) updates the subscription's billing.period when the plan change takes effect. ONE_TIME products are not allowed here; they are only billed on the first cycle of a new subscription.
By default the new plan takes effect on the next billing date; pass is_immediate to bill the new plan right away and reset the billing anchor to today. The pending plan is visible on the subscription as change_plan_items and change_plan_at until it takes effect.
Path
POST /subscriptions/{subscription_id}/change-plan
| Path Parameter | Type | Description | Example |
|---|---|---|---|
| subscription_id | String(32) | The subscription to change | sub_Wt5RmK2xPqLv9nYcE7aBz |
Example
{
"items": [
{
"product_id": "pro_premium1...", // replaces the current recurring lines
"qty": 1
}
],
"is_immediate": false, // [optional] default false — apply on the next billing date; true bills the new plan now and resets the billing anchor
"signature": "secret-key-for-payload" // [optional] shared-secret signature for the payload, see the signature section below
}
Request Parameters
Field | Required | Type | Description | Example |
|---|---|---|---|---|
| items | Y | Array | New RECURRING line items; replaces the current lines and re-derives the billing period from the products — same shape as on create | See example |
| is_immediate | N | Boolean | Bill the new plan immediately and reset the billing anchor to today. Default false — the new plan takes effect on the next billing date | false |
| signature | N | String | Optional passphrase signature for verifying the payload | secret-key-for-payload |
Response Body
{
"status": true,
"result": {
"id": "sub_Wt5RmK2xPqLv9nYcE7aBz",
"customer_id": "cus_abc123...",
"subscription_status": "ACTIVE",
"change_plan_at": "2026-09-01T00:00:00Z",
"change_plan_items": [
{
"product_id": "pro_premium1...",
"qty": 1
}
],
"date_next_billing": "2026-09-01"
}
}
Response Parameters
Field | Type | Description | Example |
|---|---|---|---|
| status | Boolean | Whether the plan change was scheduled or applied | true |
| result.id | String(32) | The subscription the plan change belongs to | sub_Wt5RmK2xPqLv9nYcE7aBz |
| result.customer_id | String(32) | Associated customer ID | cus_abc123... |
| result.subscription_status | ENUM | Subscription state, see lookups | ACTIVE |
| result.change_plan_at | String | ISO timestamp when the new plan takes effect; null once applied | 2026-09-01T00:00:00Z |
| result.change_plan_items | Array | The pending recurring line items; null once applied | ... |
| result.date_next_billing | String | Next billing date | 2026-09-01 |
Pause Request
Pause an ACTIVE or TRIAL subscription. No charges occur while paused and the billing schedule is suspended. Resume at any time with the resume request.
Path
POST /subscriptions/{subscription_id}/pause
| Path Parameter | Type | Description | Example |
|---|---|---|---|
| subscription_id | String(32) | The subscription to pause | sub_Wt5RmK2xPqLv9nYcE7aBz |
Example
An empty body (or {}) is valid.
{
"signature": "secret-key-for-payload" // [optional] shared-secret signature for the payload, see the signature section below
}
Response Body
{
"status": true,
"result": {
"id": "sub_Wt5RmK2xPqLv9nYcE7aBz",
"customer_id": "cus_abc123...",
"subscription_status": "PAUSED",
"date_next_billing": null,
"paused_at": "2026-08-15T09:20:00Z"
}
}
Resume Request
Resume a PAUSED subscription. Billing restarts on the next scheduled date; pass is_bill_now to charge the current cycle immediately and reset the billing anchor to today.
Path
POST /subscriptions/{subscription_id}/resume
| Path Parameter | Type | Description | Example |
|---|---|---|---|
| subscription_id | String(32) | The subscription to resume | sub_Wt5RmK2xPqLv9nYcE7aBz |
Example
An empty body (or {}) is valid.
{
"is_bill_now": false, // [optional] default false — resume on the next scheduled billing date; true charges the current cycle now and resets the billing anchor
"signature": "secret-key-for-payload" // [optional] shared-secret signature for the payload, see the signature section below
}
Response Body
{
"status": true,
"result": {
"id": "sub_Wt5RmK2xPqLv9nYcE7aBz",
"customer_id": "cus_abc123...",
"subscription_status": "ACTIVE",
"date_next_billing": "2026-09-01",
"resumed_at": "2026-08-20T09:20:00Z"
}
}
Cancel Request
Cancel a subscription. By default the cancellation takes effect at the end of the current billing period — the customer keeps access until the next billing date and no further charges occur. Pass is_immediate to cancel right away. Cancellation is permanent; create a new subscription to bill the customer again.
Path
POST /subscriptions/{subscription_id}/cancel
| Path Parameter | Type | Description | Example |
|---|---|---|---|
| subscription_id | String(32) | The subscription to cancel | sub_Wt5RmK2xPqLv9nYcE7aBz |
Example
An empty body (or {}) is valid.
{
"is_immediate": false, // [optional] default false — cancel at the end of the current billing period
"reason": "Customer downgraded", // [optional] recorded against the cancellation for reporting
"signature": "secret-key-for-payload" // [optional] shared-secret signature for the payload, see the signature section below
}
Request Parameters
Field | Required | Type | Description | Example |
|---|---|---|---|---|
| is_immediate | N | Boolean | Cancel immediately instead of at the end of the current billing period. Default false | false |
| reason | N | String | Optional reason recorded against the cancellation for reporting | Customer downgraded |
| signature | N | String | Optional passphrase signature for verifying the payload | secret-key-for-payload |
Response Body
{
"status": true,
"result": {
"id": "sub_Wt5RmK2xPqLv9nYcE7aBz",
"customer_id": "cus_abc123...",
"subscription_status": "ACTIVE",
"date_cancel": "2026-09-01",
"cancel_reason": "Customer downgraded",
"date_next_billing": null
}
}
Response Parameters
Field | Type | Description | Example |
|---|---|---|---|
| status | Boolean | Whether the cancellation was scheduled or applied | true |
| result.id | String(32) | The subscription the cancellation belongs to | sub_Wt5RmK2xPqLv9nYcE7aBz |
| result.customer_id | String(32) | Associated customer ID | cus_abc123... |
| result.subscription_status | ENUM | Remains ACTIVE until the scheduled cancellation date, then CANCELLED; CANCELLED immediately when is_immediate is true, see lookups | ACTIVE |
| result.date_cancel | String | Date the cancellation takes effect | 2026-09-01 |
| result.cancel_reason | String | Reason recorded against the cancellation | Customer downgraded |
| result.date_next_billing | String | null — no further billing occurs | null |
Failed payments
When an AUTOCHARGE billing cycle declines on all cards, the charge is retried daily for up to 3 days. Each attempt fires subscription.charge_failed. If all retries are exhausted, the subscription moves to FAILED and billing stops until a successful payment is collected — for example after the customer stores a new card via a Card Vault Link, the next retry or a manual Card Vault Charge restores the subscription to ACTIVE.
Signature creation
When creating API keys on the dashboard you can download a passphrase key, use it to generate your signature and send it in the signature parameter. The canonicalization and HMAC-SHA256 process is identical across all endpoints — see Checkout Link — Signature creation for Node.js, PHP, C#, Java, and Python examples.
Webhook
Webhooks are delivered to notification.webhook_url for each subscription lifecycle event when that field was supplied on create. Broader platform webhooks are configured separately if applicable. Billing-cycle webhooks fire once per cycle outcome, not per cascade attempt.
Possible event values include subscription.created, subscription.charged, subscription.charge_failed, and others listed under Webhook events.
Webhook Payload
{
// subscription.created · subscription.activated · subscription.charged · subscription.charge_failed ·
// subscription.plan_changed · subscription.paused · subscription.resumed · subscription.cancelled ·
// subscription.expired · subscription.failed
"event": "subscription.charged",
"data": [
{
"subscription": {
"id": "sub_Wt5RmK2xPqLv9nYcE7aBz",
"customer_id": "cus_abc123...",
"reference": "SUB-2026-00042",
"subscription_status": "ACTIVE",
"collection_method": "AUTOCHARGE",
"total_recurring_excl": "600.46",
"total_recurring_incl": "690.53",
"currency": "ZAR",
"billing": {
"period": "MONTHLY",
"billing_day": 1,
"date_start": "2026-08-01",
"date_end": "2027-07-31"
},
"date_last_billing": "2026-08-01", // present from the first billing cycle
"date_next_billing": "2026-09-01",
"card_id": "crd_9kLmXw3RtYqPz8vNcE2aB", // card charged for this cycle; present on subscription.charged
"transaction_id": "tra_pr6CvR_4pvWwmgQ4y3dtY", // present on subscription.charged
"invoice_id": "inv_k2Jd8sLqPz...", // present when invoice.is_generate was true
"error": null, // decline details; present on subscription.charge_failed
"metadata": {
"order_id": "ord_98765"
},
"completed_at": "2026-08-01T06:00:00Z"
}
}
],
"created_at": "2026-08-01T06:00:00Z"
}
Webhook Payload Parameters
Field | Type | Description | Example |
|---|---|---|---|
| event | String | Type of webhook event that occurred | subscription.charged |
| data | Array | Array containing subscription data | ... |
| data.subscription.id | String(32) | Unique subscription identifier | sub_Wt5RmK2xPqLv9nYcE7aBz |
| data.subscription.customer_id | String(32) | Associated customer ID | cus_abc123... |
| data.subscription.reference | String(35) | Your reference for this subscription | SUB-2026-00042 |
| data.subscription.subscription_status | ENUM | Subscription state after the event, see lookups | ACTIVE |
| data.subscription.collection_method | ENUM | How each cycle is collected, see lookups | AUTOCHARGE |
| data.subscription.total_recurring_excl | String | Recurring total per cycle, excluding tax | 600.46 |
| data.subscription.total_recurring_incl | String | Recurring total per cycle, including tax | 690.53 |
| data.subscription.currency | String(3) | ISO 4217 currency code | ZAR |
| data.subscription.billing | Object | Resolved billing schedule | See webhook payload |
| data.subscription.date_last_billing | String | Most recent billing date | 2026-08-01 |
| data.subscription.date_next_billing | String | Next billing date; null when no further billing occurs | 2026-09-01 |
| data.subscription.card_id | String(32) | Card charged for this cycle; present on subscription.charged | crd_9kLmXw3RtYqPz8vNcE2aB |
| data.subscription.transaction_id | String(32) | Transaction for this cycle; present on subscription.charged | tra_pr6CvR_4pvWwmgQ4y3dtY |
| data.subscription.invoice_id | String(32) | Invoice for this cycle when invoice.is_generate was true | inv_k2Jd8sLqPz... |
| data.subscription.error.code | ENUM | Decline code; present on subscription.charge_failed, see lookups | INSUFFICIENT_FUNDS |
| data.subscription.error.message | String | Human-readable decline reason; present on subscription.charge_failed | The transaction was declined due to insufficient funds |
| data.subscription.metadata | Object | Custom key/value metadata supplied on create | {"order_id": "ord_98765"} |
| data.subscription.completed_at | String | ISO timestamp when the subscription reached the status for this event | 2026-08-01T06:00:00Z |
| created_at | String | ISO timestamp when webhook was created | 2026-08-01T06:00:00Z |
Webhook Events
| Event | Description | Trigger Condition | Data Included |
|---|---|---|---|
subscription.created | The subscription was created | When the create request succeeds | Subscription details, billing schedule, totals |
subscription.activated | The subscription became active | When the trial ends or the first charge succeeds | Subscription details, next billing date |
subscription.charged | A billing cycle was collected successfully | When the cycle charge succeeds on any card in the cascade | Subscription details, charged card, transaction, invoice when generated |
subscription.charge_failed | A billing cycle charge attempt failed | When a cycle charge declines on all attempted cards; fires once per retry | Subscription details, decline code and message |
subscription.plan_changed | The recurring line items changed | When a scheduled or immediate plan change takes effect | Subscription details, new items and totals |
subscription.paused | The subscription was paused | When a pause request completes | Subscription details |
subscription.resumed | The subscription was resumed | When a resume request completes | Subscription details, next billing date |
subscription.cancelled | The subscription was cancelled | When an immediate cancellation completes, or a scheduled cancellation takes effect | Subscription details, cancellation reason |
subscription.expired | The subscription reached its end date | When billing.date_end passes | Subscription details |
subscription.failed | Billing stopped after exhausted retries | When all retries of a failed cycle are exhausted | Subscription details, last decline code and message |
Webhook Security
All webhooks are sent with the following headers for verification:
X-Signature: HMAC-SHA256 signature of the payloadX-Timestamp: Unix timestamp of when the webhook was sentUser-Agent:Kwik-Webhooks/1.0
Webhook Response
Your endpoint should respond with a 200 status code to acknowledge receipt. Failed webhooks will be retried up to 3 times with exponential backoff.
Electronic Mandates
Hosted web pages that new customers can use to signup with or existing customers can use to add collections to their account.
Checkout Link
Create a secure, customizable checkout link session to capture payments with cards, bank transfers, and other payment methods. Supports 3D Secure authentication, cards storage for recurring billing, invoice issuance, customer creation, and webhook notifications.