> ## Documentation Index
> Fetch the complete documentation index at: https://developer.novacpayment.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscription Services

> Learn how to save customer cards and charge them automatically on a recurring schedule using Novac's card tokenisation and recurring billing APIs.

# Overview

Subscription businesses such as SaaS products, membership platforms, content services need to charge customers on a regular schedule without asking them to re-enter payment details each time.

Novac supports this through **card tokenisation** on the customer's first payment, Novac securely saves their card and returns a token. All future charges use that token, no manual input, no interrupted billing cycles.

***

## How It Works

```mermaid theme={null}
sequenceDiagram
  participant C as Customer
  participant S as Your Server
  participant N as Novac

  Note over C,N: First payment — card details captured and tokenised

  C->>S: Subscribes and enters card details
  S->>N: POST /checkout (initiates session)
  N-->>C: Hosted or custom checkout
  C->>N: Completes payment
  N-->>S: Webhook: notifyType = "successful"
  S->>N: GET /checkout/{ref}/verify
  N-->>S: Returns transaction + card.token
  S->>S: Stores card.token against customer

  Note over C,N: Subsequent billing cycles — no customer action required

  S->>N: POST /tokenized-card-charge (using stored token)
  N-->>S: Payment processed
  N-->>S: Webhook: notifyType = "successful" or "failed"
```

***

### Prerequisites

<Accordion title="See details" defaultOpen={true}>
  * [Create an account](/docs/getting-started/create-merchant-account) with completed KYC
  * [Obtain your API keys](/docs/getting-started/obtain-api-keys) — Public key for checkout initiation, Secret key for tokenised charges
  * A **webhookURL** registered in your Novac dashboard for payment status notifications
  * A database field to store each customer's `card.token`
</Accordion>

***

### Capture and Tokenise the Card

On signup or plan activation, initiate a standard checkout. After payment is completed and verified, the transaction response includes a `card.token` that represents the customer's saved card.

#### Create a Checkout Session

```bash Request theme={null}
curl --request POST \
  --url https://api.novacpayment.com/api/v1/checkout \
  --header 'Authorization: Bearer <your-public-key>' \
  --header 'Content-Type: application/json' \
  --data '{
    "amount": 5000,
    "currency": "NGN",
    "email": "subscriber@example.com",
    "reference": "SUB-INITIAL-00789",
    "callbackUrl": "https://yourapp.com/payment/callback",
    "redirectUrl": "https://yourapp.com/dashboard"
  }'
```

Redirect the customer to the returned `checkoutUrl` to complete payment.

#### Verify the Transaction and Extract the Token

After the customer pays and is redirected to your `callbackURL`, verify the transaction server-side:

```bash Request theme={null}
curl --request GET \
  --url https://api.novacpayment.com/api/v1/checkout/SUB-INITIAL-00789/verify \
  --header 'Authorization: Bearer <your-secret-key>'
```

```json Response (excerpt) theme={null}
{
  "status": true,
  "data": {
    "status": "successful",
    "transactionReference": "SUB-INITIAL-00789",
    "amount": 5000,
    "card": {
      "first6Digits": "539983",
      "last4Digits": "8381",
      "issuer": "Access Bank",
      "type": "mastercard",
      "token": "tok_abc123xyz789"
    },
    "customer": {
      "email": "subscriber@example.com",
      "name": "Emeka Nwosu"
    }
  }
}
```

<Warning>
  Never store raw card numbers, CVV, or PINs on your servers. Store only the `card.token` value returned by Novac.
</Warning>

Save `card.token` in your database linked to the customer's account. This token is what you'll use for all future billing cycles.

[Full guide → Verify a Transaction](/docs/accept-payment/manage-payment/verify-transaction)

***

### Subsequent Billing - Charge the Saved Card

When a subscription renewal is due (daily, weekly, monthly), charge the customer's saved card directly — no checkout page needed, no customer action required.

```bash Request theme={null}
curl --request POST \
  --url https://api.novacpayment.com/api/v1/tokenized-card-charge \
  --header 'Authorization: Bearer <your-secret-key>' \
  --header 'Content-Type: application/json' \
  --data '{
    "token": "tok_abc123xyz789",
    "currency": "NGN",
    "amount": "5000",
    "email": "subscriber@example.com",
    "firstName": "Emeka",
    "lastName": "Nwosu",
    "reference": "SUB-RENEWAL-00790"
  }'
```

<Note>
  The `email` value must match exactly the one used when the original checkout was created.
</Note>

[Full guide here, save and charge customer's card](/docs/accept-payment/manage-payment/recurring-billing)

***

### Handle Payment Outcomes via Webhook

Tokenised charges happen server-to-server with no customer involvement. Your webhook endpoint is the primary way to know whether a renewal succeeded or failed.

```json Successful Renewal theme={null}
{
  "notify": "transaction",
  "notifyType": "successful",
  "data": {
    "transactionReference": "SUB-RENEWAL-00790",
    "amount": 5000,
    "status": "successful",
    "customer": { "email": "subscriber@example.com" }
  }
}
```

```json Failed Renewal theme={null}
{
  "notify": "transaction",
  "notifyType": "failed",
  "data": {
    "transactionReference": "SUB-RENEWAL-00790",
    "amount": 5000,
    "status": "failed",
    "gatewayResponseCode": "51",
    "customer": { "email": "subscriber@example.com" }
  }
}
```

**Recommended handling for failed renewals:**

| Scenario           | Recommended Action                                        |
| ------------------ | --------------------------------------------------------- |
| Insufficient funds | Retry after 24–48 hours, notify customer                  |
| Card expired       | Prompt customer to update card details via a new checkout |
| Repeated failures  | Suspend subscription, send dunning email                  |

[Full guide > Webhooks](/docs/api-basics/webhooks)

***

### Updating a Customer's Card

When a customer's card expires or they want to use a different card, initiate a new checkout session to capture the new card details and replace the stored token.

Use the same verification flow when extracting the new `card.token` and update your database record for that customer.

***

## What's Next?

* **Save and Charge Customer** - Full technical reference for [card tokenisation](/docs/accept-payment/manage-payment/recurring-billing) and tokenised charges.
* **Refund a Transaction** - [Issue full or partial refunds](/docs/accept-payment/manage-payment/refund-transaction) when a subscriber cancels mid-cycle.
* **Webhooks** - Set up and secure your [webhook](/docs/api-basics/webhooks) endpoint for renewal notifications.
