Skip to main content

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.

Base URL

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.
Choosing between AutoPay and Auto-Debit

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_url from the response to pay the first charge.
  • Confirm activation: read extra.autopay.subscription_id from the webhook, then retrieve the subscription until it leaves pending_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.
Boost Your Integration

Ottu offers SDKs and tools to speed up your integration. See Getting Started for all available options.

Guide​

Workflow​

AutoPay subscription flow The merchant makes one Checkout API call with payment_type auto_pay, and Ottu creates the subscription synchronously. The merchant redirects the customer to the checkout page, where the customer enters their card and pays the first charge, the CIT. Ottu then sends the result to the merchant's webhook URL. From then on the billing cycles, retries, dunning, and the customer self-service page are all handled for the merchant, who makes no further calls to keep the subscription running. OTTU PLATFORM Customer Merchant Backend Your server Checkout Page Ottu-hosted or SDK embed Subscription Created by your checkout call Handled for you Billing cycles · retries Dunning · notifications Customer self-service page checkout call · auto_pay redirect to checkout enters card · pays (CIT) submits payment ongoing webhook · result (async)
  1. You create the subscription with one Checkout API call that describes the plan and its schedule.
  2. Your customer pays the first charge on the checkout page, and Ottu saves their card.
  3. 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.
  4. Ottu bills each cycle, retries failed charges and emails your customer.
  5. 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.

  1. 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.
  2. 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.
  3. 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:

  • status is pending_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 status leaves pending_setup. Do not grant access from the webhook's autopay block alone: it is not signed and can be missing.
  • If a subscription is still pending_setup well 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:

StateMeaning
pending_setupCreated by the checkout call; waiting for the customer to complete the first payment.
trialingThe first payment settled with a 0.000 amount. No money moved, but the schedule is live.
activeBilling normally.
past_dueA billing cycle used up every retry. See Retries & Dunning.
canceledTerminal. No more charges.
expiredTerminal. The subscription's end_date was reached.
setup_failedThe 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 amountWhat the customer pays at checkoutCycle 1Cycle 2
Greater than 0amount, charged at checkoutThat charge, charge_type: "cit", scheduled_date = start_date, already paidOne period (month or year) after start_date
0.000 (trial)Nothing. The card is saved only.First real charge, one period after start_dateThe 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.

Ottu never auto-cancels a past-due subscription

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.

Customer cancellation is end-of-period

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).

Create an AutoPay subscription — POST /b/checkout/v1/pymt-txn/
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 a subscription with the Checkout API: set payment_type to auto_pay and send the autopay block.

Create a new Payment Transaction​

Create a new Payment Transaction

POST 

/b/checkout/v1/pymt-txn/

Create a new Payment Transaction

Permissions​

Auth MethodRequired Permissions
API KeyAll permissions (admin access)
Basic AuthCan add payment requests (Payment Request) or Can add e-commerce payments (E-Commerce)

Gateway permission: Can use pg_code for the target payment gateway

info

The PUT operation cannot be used if the user does not have permission to use the previously defined payment gateway code on the transaction.

Creating an AutoPay subscription. Set payment_type to auto_pay and send the autopay block. Six things are easy to miss:

  • agreement is a full recurring agreement, not only an id. Because the agreement type defaults to recurring, agreement.id, frequency, amount_variability, cycle_interval_days, total_cycles and expiry_date are all required. A missing field is rejected with a 400 that names it. Repeat the same schedule in the autopay block: the agreement is what the gateway sees, and the autopay block is what Ottu bills on.
  • customer_id is required.
  • language is optional and defaults to en. It sets the language of the customer's self-service page and of every customer email, and cannot be changed afterwards.
  • customer_email is required, because every customer email goes there. A missing one returns a 400 with the error under the autopay key, which looks like a problem with the autopay block. Check customer_email first.
  • pg_codes must name a gateway that supports tokenization and auto-debit, because Ottu charges every renewal by auto-debit against the card saved at checkout.
  • amount is the first charge only. "0.000" creates a trial: the card is saved, no money moves, and the subscription starts in trialing instead of active.

The 201 response carries extra.autopay.subscription_id. Store it: it is your handle on the subscription. The autopay block is write-only and is not echoed back. Every call with payment_type: "auto_pay" creates a new subscription, so guard against double submits on your side. See the AutoPay guide.

curl --location 'https://sandbox.ottu.net/b/checkout/v1/pymt-txn/' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Api-Key YOUR_API_KEY' \
--data '{
  "type": "e_commerce",
  "amount": "10.000",
  "currency_code": "KWD",
  "pg_codes": [
    "knet"
  ]
}'

Request​

Responses​

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.

StatusMeaningWhat to do
400Ottu 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.
401Not authenticated.Check your API key.
404No such subscription for your merchant.Do not retry.
409Idempotency-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.
422Ottu 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.
423The Ottu installation is paused (code: service_paused). All six subscription endpoints return it.Retry later.
503The subscription service is unavailable.Retry with backoff.
504The 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_codes must name a gateway that supports tokenization and auto-debit.
  • Billing periods. autopay.frequency is monthly or yearly. There is no weekly or custom interval.
  • No edits. A running subscription cannot be edited: amount, autopay.frequency, billing day, retry count, language, notification_preferences or 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_due alert. A past_due subscription is not billed again until the customer pays or you cancel it (see Retries & Dunning). Ottu does not notify you, so poll List subscriptions with status: "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-Key on cancel and regenerate. Only cancel replays safely. Before retrying a timed-out regenerate, call page-link and compare page_url.
  • Get page_url from page-link, not regenerate. The create response doesn't include it; page-link works any time after create, and regenerate is only for revoking a link.
  • Deliver page_url yourself, 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 a 400 with the error under the autopay key, which looks like a problem with the autopay block. Check customer_email first.
  • Expect auto_debit in the SDK payload. The Checkout SDK preload payload for an auto_pay session carries payment_type: "auto_debit" and no autopay key, because Ottu charges every renewal as an ordinary auto-debit payment. That is not a defect. The Checkout API response still reports auto_pay.

FAQ​

What's Next?​