AutoPay
AutoPay is Ottu's managed subscriptions feature. You make one Checkout API call with payment_type: "auto_pay", and Ottu then generates each billing cycle, retries failed charges, sends the dunning emails and hosts a self-service page for your customer. With Recurring Payments & Auto-Debit you own that schedule yourself. Want to see the result first? See what your customers see on the business page.
Every call on this page uses the standard Ottu API key, with no separate credential. AutoPay is API-only. See Limits.
Every API call in this guide targets https://sandbox.ottu.net. Swap in your own merchant domain when you integrate.
When to Use
- Subscriptions and SaaS billing: monthly or yearly plans where you don't want to build and operate a billing scheduler.
- You want Ottu to handle dunning: failed-charge retries, the past-due state, and recovery emails happen automatically.
- You want a customer self-service surface without building one: a hosted page for viewing status, paying an outstanding balance, updating the card, or canceling.
- You have no plan catalog to manage: there's no "create a plan" step; pricing and scheduling are just fields on your checkout call.
Use AutoPay when you want Ottu to own the whole subscription lifecycle after one checkout call. If you'd rather run the billing schedule and retry logic yourself and just charge a saved card on demand, use Recurring Payments & Auto-Debit instead. It is the closer fit for installments, on-demand billing, and cases where your own system needs to decide exactly when a charge happens.
Setup
By the end of this page your backend creates a subscription, sends the customer to pay, learns the result, and hands the customer a link to manage it.
Build
- Create the subscription with the Checkout API and store the subscription ID it returns.
- Send the customer to the
checkout_urlfrom the response to pay the first charge. - Confirm activation: read
extra.autopay.subscription_idfrom the webhook, then retrieve the subscription until it leavespending_setup. - Get the customer's page link and send it to the customer.
- Poll List subscriptions with
status: "past_due"to catch failed renewals.
Test
- Run one subscription end to end in the Live Demo.
Go live
- Switch to your production API key and base URL. No other request changes.
Ottu offers SDKs and tools to speed up your integration. See Getting Started for all available options.
Guide
Workflow
- You create the subscription with one Checkout API call that describes the plan and its schedule.
- Your customer pays the first charge on the checkout page, and Ottu saves their card.
- You get the result. When your customer completes checkout, Ottu sends the result to your webhook URL, if you set one, as for any checkout. That is the only webhook you get: renewals don't send one, so you read their outcome from the subscription, which you can look up at any time.
- Ottu bills each cycle, retries failed charges and emails your customer.
- Your customer manages the subscription from their own page. You send them the link.
Live Demo
Run the whole journey against the sandbox: create a subscription, pay its first charge with a test card, receive the webhook, and read the subscription and the customer's page link. Each step shows the real request and response. No real money moves.
Try an AutoPay subscription
Create a subscription, pay the first charge with a test card, then watch it activate — all in the sandbox.
What your customer sees
Your customer meets AutoPay in three places. See What your customer sees on the business page for the full tour.
- The first-charge checkout. Your customer pays the first charge on Ottu's checkout page. Ottu saves their card, so the later charges need no action from them.
- The self-service page. Your customer opens the private link you send them. They see their status and billing history, add or switch a card, pay an overdue balance, and cancel or undo a pending cancellation.
- One email: the charge reminder. Ottu emails your customer before each charge. The email carries your business name, your support email and a link to the self-service page.
Use Cases
After the first payment Ottu runs the subscription. These are the behaviours you can rely on. The business page covers the same ground without the API detail.
First payment and activation
The first payment is a CIT (customer-initiated transaction): your customer pays on the checkout page, and Ottu saves their card so it can charge the later cycles without them. See Recurring Payments & Auto-Debit for the CIT/MIT background.
Activation lags the payment. Your customer can pay while the subscription still shows pending_setup. Ottu confirms the first payment on a recurring check. In production that takes up to about 15 minutes. On the sandbox it usually takes a minute or two. Until then:
statusispending_setup.- Your checkout webhook arrives in that state. Treat it as "payment received, activation pending", not as a failure.
- Do not hard-code a wait. Retrieve the subscription and poll until
statusleavespending_setup. Do not grant access from the webhook'sautopayblock alone: it is not signed and can be missing. - If a subscription is still
pending_setupwell after a successful payment, contact Ottu support with the subscription ID.
If the customer never pays, the subscription becomes setup_failed after 24 hours, or at once if they cancel the checkout. Ottu does not retry it; create a new subscription.
Match the webhook to the subscription. Read extra.autopay.subscription_id in the webhook payload: it is the subscription ID you stored when you created the subscription. As a fallback, the webhook's session_id equals setup_session_id on the subscription.
Subscription States
A subscription is always in exactly one of seven states:
| State | Meaning |
|---|---|
pending_setup | Created by the checkout call; waiting for the customer to complete the first payment. |
trialing | The first payment settled with a 0.000 amount. No money moved, but the schedule is live. |
active | Billing normally. |
past_due | A billing cycle used up every retry. See Retries & Dunning. |
canceled | Terminal. No more charges. |
expired | Terminal. The subscription's end_date was reached. |
setup_failed | The customer never completed the first payment. Ottu does not retry it; create a new subscription. |
A nonzero first charge makes a subscription active; a 0.000 one starts it in trialing. See Lifecycle and billing cycles for the business view.
Billing Cycles
Cycles are generated one at a time, so the next one isn't created until the previous one is paid. Each cycle locks its own amount_due when it's created. Billing is anchor-day clamped: a subscription anchored on the 31st charges on the 28th (or 29th) in February, then returns to the 31st. See Lifecycle and billing cycles.
start_date does not delay the checkout charge. The customer pays it on the checkout page, whenever they complete checkout.
Checkout amount | What the customer pays at checkout | Cycle 1 | Cycle 2 |
|---|---|---|---|
Greater than 0 | amount, charged at checkout | That charge, charge_type: "cit", scheduled_date = start_date, already paid | One period (month or year) after start_date |
0.000 (trial) | Nothing. The card is saved only. | First real charge, one period after start_date | The period after that |
Retries & Dunning
A failed charge is retried one hour apart. The default is 3 retries, 4 attempts in total, and you can set it from 1 to 10 with retry_count on the autopay block. When the last attempt fails, the cycle becomes failed, the subscription becomes past_due, and the customer gets a final email with a link to pay the balance. See When a payment fails.
A past_due subscription stays that way until the customer pays or you cancel it.
Notifications
Ottu emails your customer an upcoming-charge reminder, a payment-failed notice after each failed attempt while retries remain, and a final-failure email when they run out. Monthly subscriptions get one reminder, about 3 days before the charge. Yearly ones get three, about 31, 11 and 4 days before. Each email can be switched off per subscription with notification_preferences on the autopay block. The language comes from the checkout language field when you create the subscription (default en). It drives the customer page and every customer email. See The emails.
Customer Self-Service Page
The page_url you read from the page-link endpoint is a credential: anyone holding it can act on the subscription. Your customer can view status and billing history, add or switch a card, pay an outstanding balance, and cancel or undo a pending cancellation. See The self-service page.
A cancellation from the self-service page takes effect at the end of the current billing period. Only the merchant cancel call with mode: "immediate" stops a subscription right away. The customer can undo a pending cancellation while the subscription is active.
A customer cancellation on a past_due subscription only schedules the cancellation: the subscription stays past_due. If the customer then pays the balance, the scheduled cancellation takes effect at once and the subscription becomes canceled, with no further charge. If the customer never pays, the subscription stays past_due until you cancel it with mode: "immediate".
API Reference
All six subscription-management endpoints, plus the Checkout API call that creates a subscription, are in the interactive reference below. Expand any field for its type, enum values, constraints and defaults.
Every management endpoint authenticates with your API key and applies to your own merchant account. You never send a Merchant-Id header yourself.
Here is a complete auto_pay request. agreement is a full recurring agreement and the autopay block repeats the same schedule.
Replace <START_DATE> with the date of the first billing cycle (today or later, YYYY-MM-DD). The checkout payment is cycle 1, so total_cycles: 12 means 11 renewals. Set <EXPIRY_DATE> to the last day of the month of cycle 12, which is 11 months after <START_DATE> (for a start on 2026-11-01, use 2027-10-31).
curl --location 'https://sandbox.ottu.net/b/checkout/v1/pymt-txn/' \
--header 'Authorization: Api-Key <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data-raw '{
"type": "e_commerce",
"pg_codes": ["<TOKENIZABLE_PG_CODE>"],
"amount": "9.900",
"currency_code": "KWD",
"customer_id": "cust_1001",
"customer_email": "[email protected]",
"payment_type": "auto_pay",
"order_no": "order-1001",
"webhook_url": "https://merchant.example.com/ottu/webhook",
"agreement": {
"id": "AGR-1001",
"type": "recurring",
"frequency": "monthly",
"amount_variability": "fixed",
"cycle_interval_days": 30,
"total_cycles": 12,
"expiry_date": "<EXPIRY_DATE>"
},
"autopay": {
"frequency": "monthly",
"recurring_amount": "9.900",
"start_date": "<START_DATE>",
"description": "Pro Plan - monthly"
}
}'
- Create
- List
- Retrieve
- Cancel
- Billing cycles
- Page link
- Regenerate page token
Create a subscription with the Checkout API: set payment_type to auto_pay and send the autopay block.
Create a new Payment Transaction
List AutoPay subscriptions
Retrieve an AutoPay subscription
Cancel an AutoPay subscription
List AutoPay billing cycles
Retrieve an AutoPay hosted-page link
Regenerate an AutoPay hosted-page token
Error contract
These are the statuses you will meet most often, so you can handle them without parsing message text. The full list of status codes for each endpoint, with examples, is in the API Reference tabs above.
| Status | Meaning | What to do |
|---|---|---|
400 | Ottu rejected the request as malformed, for example a limit above 100 on list, an unknown cancel mode, or a missing Idempotency-Key on cancel or regenerate. | Fix the request. Retrying unchanged will fail again. |
401 | Not authenticated. | Check your API key. |
404 | No such subscription for your merchant. | Do not retry. |
409 | Idempotency-Key was already used on cancel with a different request body (code: idempotency_conflict). | Send a new key for a new request. Reuse a key only to retry the exact same request. |
422 | Ottu rejected the request. Either a value is invalid (for example an unknown status filter on list, where detail lists each invalid field), or the subscription is in a state that does not allow it, such as canceling one that has already ended (code: invalid_transition). | Fix the request, or re-read the subscription's status. Retrying unchanged will fail again. |
423 | The Ottu installation is paused (code: service_paused). All six subscription endpoints return it. | Retry later. |
503 | The subscription service is unavailable. | Retry with backoff. |
504 | The subscription service timed out. The request may still have been applied. | Retry a cancel with the same Idempotency-Key. Before retrying anything else, retrieve the subscription to see whether it changed. |
Limits
- Gateways. KNET and other gateways that cannot save a card for auto-debit cannot renew a subscription.
pg_codesmust name a gateway that supports tokenization and auto-debit. - Billing periods.
autopay.frequencyismonthlyoryearly. There is no weekly or custom interval. - No edits. A running subscription cannot be edited: amount,
autopay.frequency, billing day, retry count,language,notification_preferencesor customer email. Cancel it and create a new one. There is no proration. - Retries. You set only the retry count, and only when you create the subscription. Ottu sets the interval. See Retries & Dunning.
- No
past_duealert. Apast_duesubscription is not billed again until the customer pays or you cancel it (see Retries & Dunning). Ottu does not notify you, so poll List subscriptions withstatus: "past_due". - No dashboard screen. AutoPay is API-only. Renewal charges appear in Payment Management as normal transactions.
- Sandbox. You cannot trigger a renewal early.
Best Practices
- Send a UUID
Idempotency-Keyon cancel and regenerate. Only cancel replays safely. Before retrying a timed-out regenerate, callpage-linkand comparepage_url. - Get
page_urlfrompage-link, not regenerate. The create response doesn't include it;page-linkworks any time after create, and regenerate is only for revoking a link. - Deliver
page_urlyourself, every time. Ottu never notifies the customer when you regenerate, so an undelivered link is a customer who can't self-serve. - Always send
customer_email. It is required. A missing one returns a400with the error under theautopaykey, which looks like a problem with the autopay block. Checkcustomer_emailfirst. - Expect
auto_debitin the SDK payload. The Checkout SDK preload payload for anauto_paysession carriespayment_type: "auto_debit"and noautopaykey, because Ottu charges every renewal as an ordinary auto-debit payment. That is not a defect. The Checkout API response still reportsauto_pay.
FAQ
What's Next?
- Recurring Payments & Auto-Debit — the alternative when you want to own the billing schedule yourself.
- Checkout API — the full field reference for the call that creates a subscription.
- Webhooks — Payment Events — the notification for the first payment. Renewals don't send one.
- AutoPay for merchants — the business-side overview of the same feature.