Subscriptions

Subscriptions renew a customer on a recurring price. CHING handles the first charge, the renewal cron, retries on failure, and document issuance. A subscription's `status` is one of `active`, `trialing`, `incomplete`, `incomplete_expired`, `past_due`, or `canceled` - treat anything other than `active` or `trialing` as unbilled.

Use cases: Build SaaS billing, offer yearly plans, or run memberships with free trials.
POST/v1/subscriptions

Create a subscription and charge the first period immediately (unless the price has a trial, in which case the first charge runs at trial end).

If the first charge fails in live mode, the subscription is still created but with status incomplete and latest_charge pointing at the failed charge. The response is 200 - inspect data.status before granting access. Incomplete subs are moved to incomplete_expired after 23 hours if the payment is never completed, and the renewal cron does not bill them. Attached discounts emit discount.applied; each expires (discount.expired) once its duration runs out.

Body Parameters

NameTypeDescription
customer
stringrequiredThe customer id.
payment_method
stringActive payment method id to charge on each renewal. Required for paid prices; may be omitted only when the price has unit_amount === 0 (free plan).
price
stringrequiredA recurring price id. Determines amount and renewal cadence.
discounts
arrayOptional discounts to attach to the subscription. Each entry is either { code: "LAUNCH25" } (a coupon code) or { discount: "disc_..." } (a discount rule id). Automatic product/price rules targeting this price attach on their own and need not be listed. Each resolved rule becomes an applied_discount (di_*) that reduces the first and renewal charges for its duration (once / n_charges / until_date / forever).
metadata
objectSet of key-value pairs you can attach to the object for your own use. Returned as-is on retrieval.

Request

curl -X POST "https://api.ching.co.il/ching/v1/subscriptions" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "customer": "example_customer",
  "payment_method": "example_payment_method",
  "price": "example_price",
  "discounts": [],
  "metadata": {}
}'

Response

Response
{
  "success": true,
  "data": {
    "id": "sub_hXUPYOnvxp-q",
    "object": "subscription",
    "customer": "cus_V8ltq1pK_MWH",
    "default_payment_method": "pm_WMc9X22NT1af",
    "status": "active",
    "currency": "ils",
    "items": [
      {
        "id": "si_E4TEG8TRMHp-",
        "price": "price_QA8qF3B3VIqE",
        "quantity": 1
      }
    ],
    "billing_cycle_anchor": "2026-04-19T09:16:40.000Z",
    "current_period_start": "2026-04-19T09:16:40.000Z",
    "current_period_end": "2026-05-19T09:16:40.000Z",
    "cancel_at_period_end": false,
    "latest_charge": "ch_9mTPfRSDmEOU",
    "metadata": {},
    "livemode": false,
    "created": "2026-04-19T09:16:40.000Z"
  }
}
GET/v1/subscriptions

List the 100 most recent subscriptions, newest first. Each row carries `customer_name` for display. Line items and the next-charge estimate are omitted here - fetch the full subscription to see them.

Request

curl -X GET "https://api.ching.co.il/ching/v1/subscriptions" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Response

Response
{
  "success": true,
  "data": [
    {
      "id": "sub_hXUPYOnvxp-q",
      "object": "subscription",
      "customer": "cus_V8ltq1pK_MWH",
      "customer_name": "Dana Levi",
      "default_payment_method": "pm_WMc9X22NT1af",
      "status": "active",
      "currency": "ils",
      "items": [],
      "billing_cycle_anchor": "2026-04-19T09:16:40.000Z",
      "current_period_start": "2026-04-19T09:16:40.000Z",
      "current_period_end": "2026-05-19T09:16:40.000Z",
      "cancel_at_period_end": false,
      "next_retry_at": null,
      "metadata": {},
      "livemode": false,
      "created": "2026-04-19T09:16:40.000Z"
    }
  ]
}
GET/v1/subscriptions/:id

Retrieve a subscription by its id, including expanded items. The response adds a next-charge renewal estimate - `next_charge_subtotal` (gross before discounts), `next_charge_discount_amount` (total reduction), and `next_charge_amount` (what will actually be charged), all in agorot, where `subtotal - discount_amount = amount`. `next_charge_discounts` lists each discount that reduces the upcoming charge, with `name`, `value_type`, `value`, `duration`, `amount_off` (agorot off this charge), and the remaining duration: `charges_remaining` (set only for `n_charges`) and `ends_at` (set only for `until_date`); both are null for `once`/`forever`. The array is empty when no discount applies, and a completed or expired discount drops out of it. These `next_charge_*` fields appear only on this single-subscription GET, not on list or create. The response also carries `pending_price` and `pending_effective_at` - the price a scheduled plan change (see Change a subscription's price) will switch to at the next renewal, both null when no change is pending.

Path Parameters

NameTypeDescription
id
stringrequiredThe subscription id.

Request

curl -X GET "https://api.ching.co.il/ching/v1/subscriptions/:id" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Response

Response
{
  "success": true,
  "data": {
    "id": "sub_hXUPYOnvxp-q",
    "object": "subscription",
    "customer": "cus_V8ltq1pK_MWH",
    "default_payment_method": "pm_WMc9X22NT1af",
    "status": "active",
    "currency": "ils",
    "items": [
      {
        "id": "si_E4TEG8TRMHp-",
        "price": "price_QA8qF3B3VIqE",
        "quantity": 1
      }
    ],
    "billing_cycle_anchor": "2026-04-19T09:16:40.000Z",
    "current_period_start": "2026-04-19T09:16:40.000Z",
    "current_period_end": "2026-05-19T09:16:40.000Z",
    "cancel_at_period_end": false,
    "next_retry_at": null,
    "pending_price": null,
    "pending_effective_at": null,
    "next_charge_subtotal": 41300,
    "next_charge_discount_amount": 18054,
    "next_charge_amount": 23246,
    "next_charge_discounts": [
      {
        "name": "Reserve duty fair",
        "value_type": "override",
        "value": 19700,
        "duration": "forever",
        "charges_remaining": null,
        "ends_at": null,
        "amount_off": 18054
      }
    ],
    "metadata": {},
    "livemode": false,
    "created": "2026-04-19T09:16:40.000Z"
  }
}
POST/v1/subscriptions/:id/cancel

Cancel a subscription immediately or at period end.

Path Parameters

NameTypeDescription
id
stringrequiredThe subscription id.

Body Parameters

NameTypeDescription
cancel_at_period_end
booleanWhen true, the subscription stays active until the end of the current period and will not renew. When false or omitted, it is canceled immediately.

Request

curl -X POST "https://api.ching.co.il/ching/v1/subscriptions/:id/cancel" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "cancel_at_period_end": true
}'

Response

Response
{
  "success": true,
  "data": {
    "id": "sub_hXUPYOnvxp-q",
    "status": "canceled",
    "cancel_at_period_end": false
  }
}
POST/v1/subscriptions/:id/change_price

Switch a subscription to a different recurring price without canceling it. By default the change is auto-routed: an upgrade (the new price costs more per day) is applied immediately and charged prorated for the days left in the current period, while a downgrade is scheduled for the end of the current period. The renewal date (current_period_end) never moves - an immediate upgrade charges only the prorated amount for the remaining days, then the full new price is billed at the unchanged renewal. The current period is never refunded.

kind is upgrade, downgrade, or same. applied is true when the new price is live now (immediate upgrade) and false when scheduled. scheduled_for is the effective date of a scheduled change (= current_period_end), else null. charge_amount / charge_currency describe the prorated charge taken now, and are null when nothing was charged (scheduled change, same plan, or a free target). An applied upgrade swaps the line item immediately and its prorated charge issues a tax document (charge.succeeded); a scheduled change sets pending_price / pending_effective_at on the subscription and is applied by the renewal cron. Either path fires subscription.updated. Switching to the price the subscription is already on is a no-op (kind: same) that clears any previously scheduled change.

Path Parameters

NameTypeDescription
id
stringrequiredThe subscription id.

Body Parameters

NameTypeDescription
price
stringrequiredThe recurring price id to switch to. Must be recurring; a one-time price is rejected with price_not_recurring.
change_timing
stringWhen the switch takes effect. Omit to auto-route (upgrade now, downgrade at period end). "immediately" forces an upgrade to apply now with a prorated charge; "at_period_end" defers the change to the next renewal with no charge now. "immediately" is rejected for a downgrade (DOWNGRADE_IMMEDIATE_NOT_SUPPORTED) because the current period is never refunded.

Request

curl -X POST "https://api.ching.co.il/ching/v1/subscriptions/:id/change_price" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "price": "example_price",
  "change_timing": "example_change_timing"
}'

Response

Response
{
  "success": true,
  "data": {
    "kind": "upgrade",
    "applied": true,
    "scheduled_for": null,
    "charge_amount": 15000,
    "charge_currency": "ils",
    "subscription": {
      "id": "sub_hXUPYOnvxp-q",
      "object": "subscription",
      "customer": "cus_V8ltq1pK_MWH",
      "default_payment_method": "pm_WMc9X22NT1af",
      "status": "active",
      "currency": "ils",
      "items": [
        {
          "id": "si_E4TEG8TRMHp-",
          "price": "price_QA8qF3B3VIqE",
          "quantity": 1
        }
      ],
      "billing_cycle_anchor": "2026-04-19T09:16:40.000Z",
      "current_period_start": "2026-04-19T09:16:40.000Z",
      "current_period_end": "2026-05-19T09:16:40.000Z",
      "cancel_at_period_end": false,
      "next_retry_at": null,
      "pending_price": null,
      "pending_effective_at": null,
      "next_charge_subtotal": 41300,
      "next_charge_discount_amount": 18054,
      "next_charge_amount": 23246,
      "next_charge_discounts": [
        {
          "name": "Reserve duty fair",
          "value_type": "override",
          "value": 19700,
          "duration": "forever",
          "charges_remaining": null,
          "ends_at": null,
          "amount_off": 18054
        }
      ],
      "metadata": {},
      "livemode": false,
      "created": "2026-04-19T09:16:40.000Z"
    }
  }
}