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.com/api/v1/contracts \
  -H "Authorization: Bearer csk_test_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "merchant_id": "b1e7c0f2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
    "payment_method_type": "CARD",
    "payment_method_token": "tok_xxxxxxxxxxxx",
    "amount": "99.00",
    "currency": "USD",
    "frequency": "MONTHLY",
    "start_date": "2026-08-01"
  }'
Python
import requests, uuid

resp = requests.post(
    "https://api.cresoracommerce.com/api/v1/contracts",
    headers={
        "Authorization": "Bearer csk_test_xxxxxxxxxxxx",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "merchant_id": "b1e7c0f2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
        "payment_method_type": "CARD",
        "payment_method_token": "tok_xxxxxxxxxxxx",
        "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.com/api/v1/contracts", {
  method: "POST",
  headers: {
    Authorization: "Bearer csk_test_xxxxxxxxxxxx",
    "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: "tok_xxxxxxxxxxxx",
    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 and RESUMED. Field-level edits (amount, frequency, payment method) are not supported — cancel the contract and create a new one instead.

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
WEEKLYEvery week
BIWEEKLYEvery 2 weeks
MONTHLYEvery month
QUARTERLYEvery 3 months
ANNUALLYEvery year