Skip to main content
The examples on this page use the shared sandbox key sk_test_DOCS_SHARED_KEY. You can run them right now — no signup needed. Want your own isolated sandbox? Get one in 1 call →
Get my own sandbox →Using: sk_test_DOCS_SHARED_KEY

Before you begin

Get an API key

You need a Plinth API key. If you don’t have one yet, get one here. Sandbox keys start with sk_test_.

Steps

1

Create a customer

A customer is who you’re billing. Create one with a name, email, and optionally your own internal ID (external_ref).
curl -X POST https://api.useplinth.com/v1/customers \
  -H "Authorization: Bearer sk_test_DOCS_SHARED_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corp",
    "email": "billing@acme.ng",
    "external_ref": "acme_001"
  }'
Response
{
  "id": "cus_01JXYZ...",
  "name": "Acme Corp",
  "email": "billing@acme.ng",
  "external_ref": "acme_001",
  "balance_minor": 0,
  "created_at": "2026-06-01T00:00:00Z"
}
2

Subscribe them to a plan

Pick a plan from your catalog. The sandbox already has two — plan_pro (₦5,000/month, stored as 500000 kobo) and plan_max (₦12,000/month, stored as 1200000 kobo).
curl -X POST https://api.useplinth.com/v1/subscriptions \
  -H "Authorization: Bearer sk_test_DOCS_SHARED_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cus_01JXYZ...",
    "plan_id": "plan_pro",
    "payment_method_id": "tok_test_visa"
  }'
Response
{
  "id": "sub_01JABC...",
  "customer_id": "cus_01JXYZ...",
  "plan_id": "plan_pro",
  "state": "active",
  "billing_mode": "advance",
  "current_period_start": "2026-06-01T00:00:00Z",
  "current_period_end": "2026-07-01T00:00:00Z",
  "next_bill_at": "2026-07-01T00:00:00Z",
  "created_at": "2026-06-01T00:00:00Z"
}
3

Check their access

Before serving a feature, check if the customer has access. The entitlements endpoint tells you what tier they’re on — no parsing state machines yourself.
curl https://api.useplinth.com/v1/customers/cus_01JXYZ.../entitlements \
  -H "Authorization: Bearer sk_test_DOCS_SHARED_KEY"
Response
{
  "has_access": true,
  "tier": "full",
  "subscription_state": "active",
  "plan": "Pro"
}
If has_access is true, let them in. That’s it.

What happens next

Next month, we charge automatically. The subscription’s next_bill_at date triggers the billing engine — it charges the card on file and marks the invoice paid. If the card declines, dunning kicks in: we retry on a schedule and send you webhooks at every step. You get a subscription.past_due event when the first charge fails, subscription.recovered if we succeed later, and subscription.delinquent if we never do.

Next steps

Core concepts

Understand subscription states, invoices, and the billing lifecycle.

Card billing guide

Full walkthrough: plan creation, tokenisation, renewal handling.

Transfer billing guide

Set up virtual accounts for customers who pay by bank transfer.

Webhook reference

Every event type we emit and what the payload looks like.