Subscriptions
A Subscription binds a plan to a user/client and a default payment method.
How a subscription is createdβ
There is no public POST /v1/subscriptions endpoint. A subscription is created internally during card verification, tied to an existing transaction.
To create a subscription you call POST /v1/subscriptions/verify-card with shouldCreateSubscription: true (and a planUid). The verify-card flow tokenizes the card, pre-authorizes it against the existing transaction, reverts that authorization, and β when shouldCreateSubscription is set β creates the subscription as part of the same flow.
curl -X POST https://mw.migopayments.com/v1/subscriptions/verify-card \
-H "Authorization: Bearer <middleware-jwt>" \
-H "Content-Type: application/json" \
-d '{
"uid": "<transaction-uid>",
"processor": "<processor-slug>",
"cardInfo": { "...": "card data tokenized by the processor" },
"shouldCreateSubscription": true,
"planUid": "<plan-uid>"
}'
See Payment methods β Verify a card for the full verify-card contract.
The internal createSubscription function (invoked by the verify-card flow, not exposed as an HTTP route) takes:
| Field | Notes |
|---|---|
client | Client / tenant name |
clientId | Client identifier |
planUid | Plan to subscribe to |
currency | Subscription currency |
trxUid | Originating transaction UID |
trxId | Originating transaction id |
userId | Cardholder user id |
notificationEmail | Optional β email for subscription notifications |
There are no planId, cardholderId, cardId, externalId, metadata, trialOverrideDays, or startAt fields.
Subscription statesβ
A subscription has exactly four states:
| State | Meaning |
|---|---|
active | Paid and current |
cancelled | Cancelled by you or the cardholder |
expired | Fixed-term subscription reached its end |
inactive | Charge retries were exhausted β billing stopped |
There is no trialing, past_due, unpaid, or paused state. When charge retries are exhausted the subscription becomes inactive.
Get a subscriptionβ
curl https://mw.migopayments.com/v1/subscriptions/detail/sub_01HAAA \
-H "Authorization: Bearer <middleware-jwt>"
List subscriptionsβ
GET /v1/subscriptions requires both userId and clientId query parameters (it returns 400 if either is missing). The response is a non-paginated array.
curl "https://mw.migopayments.com/v1/subscriptions?userId=<userId>&clientId=<clientId>" \
-H "Authorization: Bearer <middleware-jwt>"
Response:
{
"success": true,
"message": "subscriptions found",
"data": [
{ "planName": "Pro Monthly", "uid": "sub_01HAAA", "URL": "https://.../subscriptions/sub_01HAAA" }
]
}
There are no status, planId, cardholderId, createdAfter, or createdBefore filters, and no page / limit pagination.
Update a subscriptionβ
PUT /v1/subscriptions only updates the subscription's notification email. It does not change plan, status, or default payment method.
curl -X PUT https://mw.migopayments.com/v1/subscriptions \
-H "Authorization: Bearer <middleware-jwt>" \
-H "Content-Type: application/json" \
-d '{
"subUid": "sub_01HAAA",
"email": "billing@example.com"
}'
Pause/resume, change-plan, and proration are not supported by the current API.
Change default payment methodβ
Use Payment methods β Set default.
Cancel a subscriptionβ
curl -X DELETE https://mw.migopayments.com/v1/subscriptions/sub_01HAAA \
-H "Authorization: Bearer <middleware-jwt>"
Cancellation is immediate: the subscription's status is set to cancelled. There are no cancelAt, immediate, or period_end options.
Notificationsβ
The subscription flow sends email notifications (via the middleware's notifyEvent mechanism) and a merchant callback (subsCallback); it does not emit a public outbound webhook contract with subscription.* events.
Email notification types emitted by the subscription/cron flows include: addPaymentMethod, deletePaymentMethod, cancelSubscription, subPayProblem, subscriptionSuspended, and notifyCardExpiration.
Events such as subscription.created, subscription.updated, subscription.trial_ending, subscription.paused, subscription.payment_succeeded, and subscription.payment_failed do not exist in the codebase.