Subscriptions tie a customer to a product and automatically track billing periods. Each renewal can be collected via virtual account bank transfer, card, or a manual confirmation. Hyparrow records every payment in a full payment history you can query at any time.
Subscriptions are linked to a product (which carries the price and currency) and a customer record. Create both before creating a subscription.
Create a subscription
POST /api/v1/subscriptions/
UUID of the customer to subscribe.
UUID of the product. The subscription amount and currency are taken from the product.
Billing frequency. One of: daily, every_3_days, weekly, biweekly, monthly, quarterly, biannual, yearly.
How each renewal is collected. One of: card, manual, va.
Number of days after a missed payment before the subscription is auto-canceled.
Arbitrary key-value pairs stored on the subscription.
URL that Hyparrow POSTs to when a checkout-link payment for this subscription changes status (completed, pending, or failed).
curl --request POST \
--url https://api.hyparrow.com/api/v1/subscriptions/ \
--header "x-api-key: your_api_key" \
--header "x-api-secret: your_api_secret" \
--header "Content-Type: application/json" \
--data '{
"customerId": "cust-uuid-...",
"productId": "prod-uuid-...",
"interval": "monthly",
"paymentMethod": "va",
"graceDays": 5,
"checkoutCallbackUrl": "https://yourapp.com/webhooks/subscription"
}'
{
"success": true,
"message": "Subscription created",
"data": {
"id": "sub-uuid-...",
"status": "pending_payment",
"interval": "monthly",
"amount": 5000.00,
"currency": "NGN",
"paymentMethod": "va",
"graceDays": 5,
"nextBillingAt": null,
"createdAt": "2025-06-01T10:00:00Z"
}
}
A new subscription starts with status: pending_payment. It becomes active once the first payment is recorded.
Subscription statuses
| Status | Meaning |
|---|
pending_payment | Created, waiting for first payment |
active | Billing is running normally |
canceled | Manually canceled |
expired | Grace period elapsed without payment |
Generate a virtual account
For subscriptions with paymentMethod: va, generate a short-lived virtual account for the current billing period.
POST /api/v1/subscriptions/:subscriptionId/generate-va
VA lifetime in minutes. Must be exactly 10, 15, or 30.
curl --request POST \
--url https://api.hyparrow.com/api/v1/subscriptions/sub-uuid-.../generate-va \
--header "x-api-key: your_api_key" \
--header "x-api-secret: your_api_secret" \
--header "Content-Type: application/json" \
--data '{ "expiryMinutes": 15 }'
{
"success": true,
"message": "Virtual account generated — pay the exact amount before it expires",
"data": {
"accountNumber": "0123456789",
"accountName": "Hyparrow / Jane Doe",
"bankName": "Wema Bank",
"bankCode": "035",
"expiresAt": "2025-06-01T10:15:00Z"
}
}
The customer must pay the exact subscription amount before the VA expires.
Mark as paid (manual)
For subscriptions with paymentMethod: manual, record a payment confirmation after collecting it through your own system.
POST /api/v1/subscriptions/:subscriptionId/pay
Your own payment reference.
Name of the payer as known by your system.
curl --request POST \
--url https://api.hyparrow.com/api/v1/subscriptions/sub-uuid-.../pay \
--header "x-api-key: your_api_key" \
--header "x-api-secret: your_api_secret" \
--header "Content-Type: application/json" \
--data '{
"reference": "TXN-20250601-001",
"payerName": "Jane Doe"
}'
Cancel a subscription
POST /api/v1/subscriptions/:subscriptionId/cancel
Cancels the subscription immediately. No further payments are collected. The canceledAt timestamp is set on the record.
curl --request POST \
--url https://api.hyparrow.com/api/v1/subscriptions/sub-uuid-.../cancel \
--header "x-api-key: your_api_key" \
--header "x-api-secret: your_api_secret"
{
"success": true,
"message": "Subscription canceled",
"data": {
"id": "sub-uuid-...",
"status": "canceled",
"canceledAt": "2025-06-01T11:00:00Z"
}
}
Get subscription status
GET /api/v1/subscriptions/:subscriptionId
curl --request GET \
--url https://api.hyparrow.com/api/v1/subscriptions/sub-uuid-... \
--header "x-api-key: your_api_key" \
--header "x-api-secret: your_api_secret"
The response includes the full subscription object with currentPeriodStart, currentPeriodEnd, nextBillingAt, and nested customer and product objects.
Payment history
GET /api/v1/subscriptions/:subscriptionId/payments
Returns a paginated list of SubscriptionPayment records, each covering a single billing cycle.
curl --request GET \
--url "https://api.hyparrow.com/api/v1/subscriptions/sub-uuid-.../payments?page=1&limit=20" \
--header "x-api-key: your_api_key" \
--header "x-api-secret: your_api_secret"
{
"success": true,
"data": [
{
"id": "pay-uuid-...",
"subscriptionId": "sub-uuid-...",
"amount": 5000.00,
"currency": "NGN",
"paidAt": "2025-06-01T10:05:00Z",
"reference": "TXN-20250601-001",
"payerName": "Jane Doe",
"periodStart": "2025-06-01T00:00:00Z",
"periodEnd": "2025-07-01T00:00:00Z",
"paymentSource": "va"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"totalPages": 1
}
}
List subscriptions
GET /api/v1/subscriptions/
| Query parameter | Type | Default | Description |
|---|
page | number | 1 | Page number |
limit | number | 20 | Results per page |
status | string | — | Filter by subscription status |
Public checkout
Share a hosted checkout page with the subscriber. No authentication is needed on their side.
GET https://api.hyparrow.com/api/v1/checkout/subscription/:subscriptionId
Hyparrow renders the payment options and, on completion, POSTs a status update to the checkoutCallbackUrl configured on the subscription.