TagPayTagPay

API Reference

Subscriptions

A Subscription enrols a customer in a Plan and charges their stored card automatically on each billing cycle. The recurring-charge cron drives all billing — you create the subscription, TagPay handles the rest.

Create a subscription

POST/v1/subscriptions

Pairs a PLN_* plan with an AUTH_* stored card to start recurring billing.

Security guard — email must match the authorization owner. The email field must be the same email the customer used when the AUTH_* token was created. This is a defence against stolen-AUTH replay — without it, a merchant could charge any tokenised card by guessing its AUTH_* code. Mismatches return 403 FORBIDDEN.

The first charge fires immediately by default. Pass start_date to delay the first cycle. One active subscription per (customer, plan) pair — re-creating returns 409 CONFLICT.

Body parameters

planstringrequired

Plan code, e.g. PLN_8mFp2Lq9KdR4nXyZ. Plan must be active.

authorizationstringrequired

Stored card authorization, e.g. AUTH_5Lp8WkQzR. The cron charges this card each cycle.

emailstringrequired

Customer email. **Must match** the email that owns the authorization. Case-insensitive.

start_datestringoptional

ISO-8601 timestamp. First charge fires on this date. Omit to charge immediately. Must not be in the past.

completed_after_chargesintegeroptional

For finite-term plans (e.g. 12-month installments). After N successful charges, the subscription flips to completed and stops billing.

metadataobjectoptional

Arbitrary key/value pairs for your own bookkeeping.

Response

201
subscription_codestring

TagPay-assigned code, prefixed with `SUB_`.

statusenum<'active' | 'paused' | 'cancelled' | 'completed' | 'past_due'>

Lifecycle state. Starts as `active`.

plan_codestring

Plan code this subscription is attached to.

customer_emailstring

Email of the customer being billed.

authorization_codestring

The `AUTH_*` token charged on each cycle.

amountinteger

Amount per cycle in kobo, inherited from the plan.

next_charge_atstring

ISO-8601 timestamp of the next scheduled charge.

last_charge_atstring | null

Last charge attempt, or null on a fresh subscription.

last_charge_statusstring | null

Result of the last charge attempt, or null.

charge_countinteger

Successful charges to date.

failed_attemptsinteger

Consecutive failed attempts. Resets to 0 on success. Hits `past_due` after the retry policy exhausts.

completed_after_chargesinteger | null

Cycle limit, or null for open-ended.

created_atstring

ISO-8601 timestamp.

updated_atstring

ISO-8601 timestamp.

Errors

NOT_FOUND404Plan or authorization not found in your account.
FORBIDDEN403Email does not match the authorization owner (stolen-AUTH guard).
VALIDATION_ERROR400Plan is inactive, or `start_date` is in the past.
DUPLICATE_REFERENCE409Customer already has an active subscription to this plan. Cancel it first.

List subscriptions

GET/v1/subscriptions

Returns subscriptions in reverse-chronological order. Scoped to the current mode based on the secret key prefix (test_sk_* vs live_sk_*).

Query parameters

statusenum<'active' | 'paused' | 'cancelled' | 'completed' | 'past_due'>optional

Filter by lifecycle state.

planstringoptional

Filter by plan code, e.g. PLN_8mFp2Lq9KdR4nXyZ.

customerstringoptional

Substring match on customer email (case-insensitive).

pageintegeroptional

Page number, 1-indexed. Defaults to 1.

per_pageintegeroptional

Results per page, max 100. Defaults to 20.

Response

200
dataarray<Subscription>

Array of subscription objects.

metaobject

Pagination metadata.

totalinteger

Total matching records.

pageinteger

Current page.

per_pageinteger

Per-page count.

page_countinteger

Total number of pages.

Retrieve a subscription

GET/v1/subscriptions/:code

Returns the full subscription resource. 404 if the code does not belong to your merchant in the current mode.

Path parameters

codestringrequired

Subscription code, e.g. SUB_jK9pLm2Q8rTuVwXy.

Response

200
subscription_codestring

Subscription code.

statusstring

Lifecycle state.

plan_codestring

Plan code.

customer_emailstring

Customer email.

authorization_codestring

Stored authorization code.

amountinteger

Amount in kobo per cycle.

next_charge_atstring

ISO-8601 next-charge timestamp.

last_charge_atstring | null

ISO-8601 timestamp of last attempt.

last_charge_statusstring | null

Result of last attempt.

charge_countinteger

Successful charges to date.

failed_attemptsinteger

Consecutive failures.

completed_after_chargesinteger | null

Cycle limit, or null.

created_atstring

ISO-8601 timestamp.

updated_atstring

ISO-8601 timestamp.

Errors

NOT_FOUND404No subscription with that code in your account.

Cancel a subscription

POST/v1/subscriptions/:code/cancel

Immediately stops billing — no further charges will fire. Cancellation is permanent: to re-enrol the customer, create a fresh subscription. Cancelling an already-cancelled subscription is a no-op (returns the existing record).

Path parameters

codestringrequired

Subscription code, e.g. SUB_jK9pLm2Q8rTuVwXy.

Body parameters

reasonstringoptional

Free-text cancellation reason. Stored on the subscription for audit, surfaced in the dashboard. Up to 500 chars.

Response

200
subscription_codestring

Subscription code.

statusstring

Will be `cancelled`.

plan_codestring

Plan code.

customer_emailstring

Customer email.

amountinteger

Amount in kobo.

Errors

NOT_FOUND404No subscription with that code in your account.

Pause a subscription

POST/v1/subscriptions/:code/pause

Pauses recurring charges. The next_charge_at is preserved — call resume and billing picks back up. Only active subscriptions can be paused; calling on any other status returns 409 CONFLICT. No body is required.

Path parameters

codestringrequired

Subscription code.

Response

200
subscription_codestring

Subscription code.

statusstring

Will be `paused`.

next_charge_atstring

Preserved schedule — billing resumes from this date once resumed.

Errors

NOT_FOUND404No subscription with that code in your account.
DUPLICATE_REFERENCE409Subscription is not in `active` state and cannot be paused.

Resume a subscription

POST/v1/subscriptions/:code/resume

Resumes a paused subscription. Billing picks back up from the preserved next_charge_at. Only paused subscriptions can be resumed; calling on any other status returns 409 CONFLICT. No body is required.

Path parameters

codestringrequired

Subscription code.

Response

200
subscription_codestring

Subscription code.

statusstring

Will be `active`.

next_charge_atstring

Next scheduled charge.

Errors

NOT_FOUND404No subscription with that code in your account.
DUPLICATE_REFERENCE409Subscription is not in `paused` state and cannot be resumed.