Skip to main content
Cresora Commerce
Integration Guides

Recurring Billing Guide

Create and manage recurring payment contracts that charge a stored payment method on a schedule.

Cresora Recurring lets you create a contract that automatically charges a stored payment method on a fixed schedule.

Concepts

  • Contract — the recurring agreement: a stored payment method, an amount, a frequency, and a schedule (start date, optional end date or installment count).
  • Installment — a single scheduled charge generated from a contract.

There is no separate "plan" or "subscription" object — the contract is the recurring entity. Each scheduled charge is materialized as a normal transaction, so it shows up in your transaction reporting like any other payment.

Prerequisites — tokenize the payment method first

A contract charges a vault token, never a raw card or bank number. Capture the payment method once via a Hosted Payment Page tokenization session, then pass the resulting token as payment_method_token. See the Tokenization Guide →.

Create a recurring contract

curl
curl -X POST https://api.cresoracommerce.ai/api/v1/contracts \
  -H "Authorization: Bearer csk_ab12cd34_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "merchant_id": "b1e7c0f2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
    "payment_method_type": "CARD",
    "payment_method_token": "cvt_01885fec-4444-7a31-9bbb-3e5b9a1f8c42",
    "amount": "99.00",
    "currency": "USD",
    "frequency": "MONTHLY",
    "start_date": "2026-08-01"
  }'
Python
import requests, uuid

resp = requests.post(
    "https://api.cresoracommerce.ai/api/v1/contracts",
    headers={
        "Authorization": "Bearer csk_ab12cd34_xxxxxxxxxxxxxxxxxxxxxxxx",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "merchant_id": "b1e7c0f2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
        "payment_method_type": "CARD",
        "payment_method_token": "cvt_01885fec-4444-7a31-9bbb-3e5b9a1f8c42",
        "amount": "99.00",
        "currency": "USD",
        "frequency": "MONTHLY",
        "start_date": "2026-08-01",
    },
)
contract = resp.json()  # contract["id"]
Node.js
const resp = await fetch("https://api.cresoracommerce.ai/api/v1/contracts", {
  method: "POST",
  headers: {
    Authorization: "Bearer csk_ab12cd34_xxxxxxxxxxxxxxxxxxxxxxxx",
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    merchant_id: "b1e7c0f2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
    payment_method_type: "CARD",
    payment_method_token: "cvt_01885fec-4444-7a31-9bbb-3e5b9a1f8c42",
    amount: "99.00",
    currency: "USD",
    frequency: "MONTHLY",
    start_date: "2026-08-01",
  }),
});
const contract = await resp.json();

Bounding the schedule (optional)

By default a contract charges indefinitely until you cancel it. To bound it, supply either:

  • end_date — stop after this date, or
  • remaining_installments — a fixed number of charges, or
  • total_amount — a fixed contract total.

Manage a contract

ActionEndpoint
Get statusGET /api/v1/contracts/{contractId}
Retry a failed installmentPOST /api/v1/contracts/{contractId}/retry
CancelPOST /api/v1/contracts/{contractId}/cancel

Contracts move through PENDING_ACTIVATION → ACTIVE → COMPLETED (or CANCELLED / FAILED), and can be PAUSED, then resumed back to ACTIVE. Limited field-level updates are supported via PATCH /api/v1/contracts/{contractId}: next_charge_date and end_date (with an optional reason). amount, frequency, and max_retries are not editable — sending any of them is rejected with 422 recurring_update_not_supported, because the amount and cadence are part of the terms the payer consented to at enrollment. The payment method cannot be changed either. To change any of these, cancel the contract and create a new one.

ACH recurring contracts

For ACH payment methods (payment_method_type of ACH_WEB, ACH_PPD, or ACH_CCD), you must also supply the NACHA authorization context on create: ach_sec_code, ach_account_type (CHECKING / SAVINGS), name_on_check, and authorization_timestamp (when the consumer authorized the debit).

🔒NACHA Reg E — ACH recurring contracts

NACHA requires you to re-notify the consumer when the debit date or amount changes, or when enough time has elapsed since the original authorization. Cresora captures the original authorization_timestamp on the contract, but sending the re-notification to your customer before the next charge is your responsibility. Monitor contract.payment_success / contract.payment_failed to track each installment.

Webhook events

EventWhen
contract.createdContract created
contract.payment_successA scheduled installment charged successfully
contract.payment_failedA scheduled installment failed (soft decline)
contract.completedFinal installment paid — contract complete
contract.pausedContract paused
contract.resumedContract resumed
contract.cancelledContract cancelled before completion

Frequencies

frequency accepts one of:

ValueMeaning
DAILYEvery day
WEEKLYEvery week
BIWEEKLYEvery 2 weeks
MONTHLYEvery month
QUARTERLYEvery 3 months
ANNUALLYEvery year