Subscription Quick Start
Use this guide to create a plan, send a customer to hosted checkout, confirm the subscription, inspect billing, and cancel the subscription.
A browser return to returnUrl is not proof that the subscription succeeded. Show a processing page, then confirm the result from a signed Subscription Event or the Subscription query API before granting access.
Prerequisites
Subscription access
DEEPayment has enabled Subscriptions for this merchant and environment.
API credentials
Use https://panama.deepayment.com/api/v1 with the production Access Key, your Ed25519 private key, and the platform body key. See Authentication.
Return URL allowlist
Every returnUrl is registered for this merchant and environment.
Subscription events
The DEEPayment operations team has configured and enabled the merchant-level HTTPS Webhook URL. Verify events with the Access Key and Secret Key for the same environment.
Query fallback
Your server can query Subscriptions, Invoices, and Payment Orders when events are delayed or unavailable.
Keep sandbox and production credentials separate. Subscription events use the same Merchant API Access Key and Secret Key for the environment; there is no separate Subscription event secret.
Integration Flow
- Create a Plan
Define the amount, currency, and billing interval. Persist the returned
planNo. - Create a Checkout Session
Send stable merchant customer, session, and subscription numbers. Persist the returned platform identifiers before redirecting the customer.
- Redirect the browser
Open the returned
checkoutUrlin the customer browser. Do not simulate hosted checkout from your server. - Handle the browser return
When the browser reaches
returnUrl, display a processing state. The customer may also close the page and never return. - Confirm the Subscription
Grant access only after a signed event or query confirms
ACTIVE. - Track billing
Use Invoices as billing facts and Payment Orders for collection results.
- Cancel when requested
Submit the cancel request and stop access only after the Subscription is confirmed as
CANCELED.
All API paths below are relative to:
https://panama.deepayment.com/api/v1
Use the common Authentication signature on every API request.
1. Create a Plan
merchantPlanNo is the merchant-side idempotency key. For MXN, amount is a positive decimal string with at most 2 decimal places. currency is a three- or four-letter code enabled for your merchant account. intervalCount must be an integer from 1 to 12; together with intervalUnit, it defines the billing interval.
POST /subscription/plans
Content-Type: application/json
{
"merchantPlanNo": "merchant_plan_monthly_001",
"name": "Monthly membership",
"description": "Monthly access",
"amount": "199.00",
"currency": "MXN",
"intervalUnit": "MONTH",
"intervalCount": 1,
"metadataJson": "{\"campaign\":\"summer\"}"
}
metadataJson is a string whose content must be a JSON object. It is not a nested JSON object.
Continue only when the response contains operation.status=3 (SUCCEEDED) and the Plan status is 2 (ACTIVE). A successful Operation confirms Plan creation; it does not confirm that any customer has subscribed.
2. Create a Checkout Session
Use stable identifiers for the same business operation:
merchantSessionNo: Checkout Session idempotency key.merchantSubscriptionNo: your Subscription identifier.merchantCustomerNo: your stable customer identifier.planNoormerchantPlanNo: provide exactly one.paymentMethod: required payment method. The current supported value isCARD.
POST /subscription/checkout-sessions
Content-Type: application/json
{
"merchantSubscriptionNo": "membership_user_1001",
"merchantSessionNo": "checkout_user_1001_001",
"planNo": "plan_example_001",
"merchantCustomerNo": "user_1001",
"paymentMethod": "CARD",
"email": "[email protected]",
"phone": "+525500000001",
"returnUrl": "https://merchant.example/subscription/result",
"metadataJson": "{\"source\":\"account_page\"}"
}
email and phone are optional customer contact snapshots; they do not control Checkout processing. DEEPayment assigns the Session validity window and returns expiresAt in the response. Do not redirect a customer after that time.
Before redirecting, persist at least:
merchantSessionNo <-> sessionNo <-> subscriptionNo
merchantSubscriptionNo <-> your customer/account
Redirect only when operation.status=3 and session.checkoutUrl is present. This means the hosted session was created; it does not mean the customer completed checkout or the Subscription is active.
3. Redirect the Customer
Return checkoutUrl to the browser and navigate the customer to it. Do not expose your Ed25519 private key to browser code.
The customer may complete checkout, abandon it, close the tab, lose connectivity, or return later. Do not make access decisions from browser parameters, screenshots, or page text.
4. Handle returnUrl
Hosted checkout may send the browser back through DEEPayment to your registered returnUrl. A direct browser close does not produce a return.
Recommended result-page behavior:
- Read the Subscription association that your server persisted before redirect.
- Display “Subscription is being confirmed.”
- Ask your server to query the Subscription.
- Update the page only from your server-confirmed state.
The return URL does not carry a trusted Subscription result.
5. Confirm the Subscription
Query by the platform Subscription number:
GET /subscription/contracts/sub_example_001
Use these states for access decisions:
| Status | Action |
|---|---|
ACTIVE (3) | Grant normal Subscription access. |
TRIALING (8) | Reserved status. Merchants cannot actively create it and must not grant access based on it. |
PENDING_CHECKOUT / ACTIVATING | Keep the customer in a processing state. |
PAST_DUE | Apply your grace-period policy and query current billing facts. |
UNPAID / CANCELED / FAILED | Do not provide normal Subscription access. |
UNKNOWN (0) | Do not newly grant access; query again. |
Subscription Events are real-time signals. Query APIs are the current-state confirmation surface. The reserved TRIALING status and processing states do not have dedicated events, so query fallback is required. Use statusVersion to reject delayed Subscription events: accept only a version greater than the last version processed for the same subscriptionNo.
6. Query Billing
An Invoice represents one Subscription billing fact. A Payment Attempt represents one collection attempt. A Payment Order represents the payment that entered DEEPayment's funds flow.
GET /subscription/invoices?subscriptionNo=sub_example_001&page=1&pageSize=20
GET /subscription/invoices/inv_example_001
GET /subscription/payment-orders?subscriptionNo=sub_example_001&page=1&pageSize=20
GET /subscription/payment-orders/FP_example_001
invoice.status=PAID confirms the Invoice was paid and the Payment Order status describes the collection result. Settlement status is not exposed by the current Subscription API; do not interpret Invoice or Payment Order payment success as a settlement confirmation.
Payment Order pages may be sparse because the current list first pages candidate Invoices and then filters Invoices without a Payment Order. Continue paging according to paging, not orders.length.
7. Cancel the Subscription
POST /subscription/contracts/sub_example_001/cancel
Content-Type: application/json
{
"reason": "Requested by customer"
}
The current API supports cancellation only after the Provider confirms CANCELED; end-of-period cancellation is not supported. reason is optional. If no reason is needed, send an empty JSON object.
If the Subscription is already CANCELED and no cancel Operation was recorded, a successful idempotent response can omit operation. Always use subscription.status to confirm the cancellation result.
Submitting the request does not by itself terminate access. Stop Subscription access only after the response, a signed event, or a query confirms CANCELED. Cancellation does not automatically refund or reverse previously confirmed Invoices, Payment Attempts, or Payment Orders.
HTTP And Operation Results
Some create or change APIs return HTTP 200 together with an operation object. Interpret both layers:
| Result | Meaning |
|---|---|
| HTTP non-2xx | No normal business response was returned. Handle the API error. A timeout or 5xx does not prove that no side effect occurred. |
HTTP 200 + SUCCEEDED | The Operation is confirmed successful; still inspect the returned business object. |
HTTP 200 + FAILED | The Operation is confirmed failed. Do not treat it as success. |
HTTP 200 + CHANNEL_UNKNOWN | The channel-side result is unknown. Do not create a replacement object with a new merchant number. |
HTTP 200 + PENDING / RUNNING | The Operation is still processing. |
Idempotency And Recovery
- Create Plan: retry with the same
merchantPlanNoand identical body. If you receivedplanNo, query it; use only anACTIVEPlan. - Create Checkout Session: retry with the same
merchantSessionNo,merchantSubscriptionNo, and identical body. There is no public Session query API; if the original result stays unknown or has nocheckoutUrl, contact support withoperationNoandtraceId. - Update or archive Plan: query the Plan. If the requested change cannot be confirmed, contact support.
- Cancel Subscription: repeat the identical request and query the Subscription. Stop access only after
CANCELEDis confirmed. - Never switch to a new merchant identifier simply because a request timed out.
See Subscription Lifecycle, Subscription Events, and the Subscriptions API Reference for the complete contract.