Resume a contract

Restarts a suspended, cancelled or cancelling recurring contract so that it charges again, optionally setting the date its next charge falls due. It is sent as an ordinary contract update: a suspended contract resumes on status: ACTIVE (with or without a next_charge); a cancelled or cancelling contract resumes only on resume: true together with a next_charge. Shuttle recognises either shape and routes it to Shuttle's dedicated resume call rather than the general update, so the operation is atomic. Charges that would have fallen due while the contract was suspended are not created retrospectively; the billing cycle restarts from the new next charge date.

Where you can do this

  • Merchant View: Contract (Confirm)
  • API: Update a contract (PUT /contracts/{contract_id}) — suspended contract: body carries status ACTIVE and/or next_charge; cancelled or cancelling contract: body carries resume true with next_charge

Before you start

  • The contract is recurring (not a one-off or a scheduled one-off) and its status is SUSPENDED, CANCELLED or CANCELLING.
  • A cancelled or cancelling contract must be given a next_charge (a date or the literal now); a suspended contract may be resumed without one.

Inputs

InputRequiredMeaning and constraints
statusconditionalACTIVE. Enough on its own to resume a suspended contract, with or without a next_charge: it is read as the trigger, and the status is set for you. It does nothing on a cancelled or cancelling contract, where resume: true is the only trigger (see Rules)
resumeconditionaltrue. Required to revive a cancelled or cancelling contract, and must be accompanied by next_charge. Redundant on a suspended contract, which resumes on status: ACTIVE or a next_charge alone, and sending it there without a next_charge turns a valid resume into a validation error, because that rule applies whatever the status. Ignored on an active contract (the request is then a plain next-charge move, Move the next charge)
next_chargeconditionalWhen the next charge falls due: yyyy-MM-dd'T'HH:mm:ss (UTC as Merchant View sends it; anything after the seconds is ignored by the parser) or the literal now. Must not be in the past. Required with resume; optional for a suspended contract
next_paymentnoDate or now for the next collection attempt against what is already outstanding. Applied only on a resume that also carries next_charge; on a resume from suspension with no next_charge it is forwarded but never read, and the contract resumes with no retry date (see Rules). A blank value is dropped by Shuttle, so a stored retry date cannot be cleared through a resume
keep_active_untilnoDate that opens or extends the keep-active window at the moment of resume, on both resume paths: the contract stays open until then and completes at that point if it is settled. A blank value does not clear a stored window (see Rules). Only ongoing contract types are held open; on any other recurring contract the date is stored and returned but never acts
occurrencesnoNew cap on the number of charges. Forwarded only if it differs from the current cap
descriptionnoApplied alongside the resume, only if it differs from the current value
alt_keynoYour reference for the contract; applied alongside the resume if it differs
metadatanoCustom key-value pairs; applied alongside the resume if they differ
amountnoThe recurring charge amount. Cannot change on a resume: a value that differs from the stored amount is refused (see Rules), one that matches is dropped and never reaches Shuttle. The comparison is numeric, so 10 and 10.00 both count as unchanged
chargesnoThe charge schedule. Cannot change on a resume: any non-empty charges array is refused, even one that repeats the current schedule; only an empty array is accepted, and it is dropped. Entries are checked for shape before that, so a malformed one is refused with its own message
event_datenoThe event date associated with the contract. Cannot change on a resume: it is compared as text against Shuttle's form of the date, yyyy-MM-dd'T'HH:mm:ss, not against the ...T00:00:00.000Z the contract read returns, so echoing back the value you read counts as a change and is refused. An empty value is dropped
payment_methodnoCannot change on a resume: any id other than the contract's current payment method is refused, and one belonging to another account is refused earlier still with "Invalid payment_method". Change it in a separate call (Change the payment method on a contract)
modify_in_placenoEdits a scheduled contract's charges in place instead of replacing the contract. Not available on a resume: any true value is refused, false or absent is dropped

Rules

Checked by the API means Shuttle refuses the request however it is sent; a screen name means only that screen refuses it, and a direct API call would be accepted.

RuleChecked byWhat you see
The fields go inside a contract object: {"contract": {... }}. The contract itself is identified by the id in the URL, not in the bodyThe APIVALIDATION_ERROR: "API body error: missing contract object"
A request is a resume when the contract is CANCELLED or CANCELLING and carries resume: true, or when it is SUSPENDED and carries next_charge or status: ACTIVE. status: ACTIVE alone on a cancelled or cancelling contract is not a resume: it is treated as an update with nothing to change and returns the contract unchanged with 200 OKThe APIsilent no-op
resume: true requires next_chargeThe APIVALIDATION_ERROR: "next_charge required"
A next_charge on a cancelled or cancelling contract without resume: true is refused (Move the next charge carries this rule)The APIVALIDATION_ERROR: "resume required"
next_charge must be in the future unless it is the literal now. Shuttle separately refuses a date more than 24 hours in the past, which the service-layer check makes unreachableThe APIVALIDATION_ERROR: "next_charge must be in the future"; Shuttle: VALIDATION_ERROR "Sorry, you need to enter a date in the future"
next_charge, next_payment and keep_active_until must parse as dates in the API's formatThe APIVALIDATION_ERROR (BOLT-7102): "Invalid next charge date" / "Invalid next payment date" / "Invalid keep active until date"
A one-off contract cannot be updated, so cannot be resumedThe APIVALIDATION_ERROR: "cannot update non-recurring contracts"
Amount, frequency, event_date, payment method, charges, legal entities and the modify_in_place, suppress_checks and bypass_validation flags cannot change on a resume. Amount, frequency, event_date and payment_method are compared with the current contract and dropped when they match, so re-sending them unchanged is safe (event_date only in Shuttle's date form, see Inputs). Charges, legal entities and the three flags are refused on presence alone: a non-empty charges or legal_entities array, or a true flag, is refused even when it repeats what is stored, so a client that re-sends a contract read verbatim is refused on a scheduled or split contract. The payment method is covered on Change the payment method on a contractThe APIVALIDATION_ERROR: "Cannot change on resume" (fields comma-separated, in the order amount, frequency, charges, event_date, payment_method, legal_entities, modify_in_place, suppress_checks, bypass_validation)
The contract must be SUSPENDED, CANCELLED or CANCELLING, and a CANCELLED or CANCELLING contract must carry a next charge date or now (mirrors the service-layer "next_charge required" rule)The APIerror code error (Shuttle INVALID_STATUS, no BOLT number): "Cannot resume contract, it is not suspended."
When next_charge is sent, the number of charges already created must be below the contract's current occurrence cap. The cap checked is the stored one; an occurrences value in the same request is applied afterwardsThe APIVALIDATION_ERROR: "Maximum number of occurrences exceeded"
next_payment must not be later than the stored next charge date (Reschedule the next payment carries this rule). A suspended contract has no stored next charge date, so the check never fires on a resume from suspensionThe APIVALIDATION_ERROR: "Invalid retry date, must not be later than next charge date"
An unknown contract id is refused by the contract read that precedes the resume; Shuttle's resume itself would silently no-op on an unknown id, as suspend does (Suspend a contract)The APIthe read's not-found error
Merchant View offers Resume only on a recurring contract in SUSPENDED, CANCELLED or CANCELLING that is not completed and not superseded, and the resume screen requires payment_contract (otherwise it redirects to the contract)Merchant View screenlink hidden / redirect
Merchant View refuses a next charge date more than one hour in the past (modal with no confirm button, "The next charge can't be in the past.") and asks for confirmation on any other date. Server-side the cut-off is "not before now" (service layer)Merchant View screenmodal; the server would also reject it
Merchant View sends no next_charge when every occurrence has already been charged, so such a resume completes the contract if nothing is outstanding rather than restarting itThe API and Merchant View screencontract becomes COMPLETED

What happens

  • The contract's status returns to ACTIVE. If no next_charge was given, nothing is outstanding and no keep-active window is open, it goes to COMPLETED instead and CONTRACT.COMPLETE is raised; if an unresolved amount remains it goes to UNRESOLVED.
  • The response carries the updated contract, and a CONTRACT.UPDATE webhook is raised.
  • Charges missed while the contract was suspended are never created. Billing restarts from next_charge: the first new charge falls due on that date (immediately for now) and later charges follow one frequency apart from it, each raising CHARGE.CREATED.
  • Arrears from before the suspension are collected with the first new charge, not at the moment of resume. Sending next_payment alongside next_charge sets the date of the next collection attempt.
  • A resume without next_charge leaves the contract ACTIVE with no next charge date: it does not charge again, and arrears are not attempted, until a date is set (Move the next charge, Reschedule the next payment or Collect a contract's arrears now).
  • keep_active_until opens or extends a keep-active window; the contract stays open until that date and completes then if it is settled.

Who can do this

  • Roles: Admin only today; intended for Support as well, and being aligned.
  • Permission keys (for clients managing permissions directly): the session must hold agreement, payment_contract or * on the client and on the contract's division; an account-scoped session is limited to its own account's contracts. Shuttle's resume call requires a user session.
  • Admin app: the resume screen requires payment_contract and redirects to the contract when the session lacks it.
  • No feature option gates this function. The keep-active window (keep_active_until) is honoured only on ongoing contract types.

Related


Did this page help you?