> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.tabs.com/api-reference/contracts/integrators-api-contractsv-3-controller-patch-commitment-schedule/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.tabs.com/_mcp/server. # Update commitment schedule PATCH https://integrators.prod.api.tabsplatform.com/v3/contracts/{id}/commitments/{commitmentId}/schedules/{scheduleId} Content-Type: application/json Reference: https://docs.tabs.com/api-reference/contracts/integrators-api-contractsv-3-controller-patch-commitment-schedule ## Authentication - `Authorization` header (required) — API Key authentication via header ## Request ### Path parameters - `id` (string, required) — Contract Id - `commitmentId` (string, required) — Commitment Id - `scheduleId` (string, required) — Schedule Id ### Body (application/json) This endpoint expects a PatchScheduleRequestDto. - `cascadeBillingTerms` (boolean, required) — Required. When true, extend or shorten step-linked base BTs (and their POBs) to match the new schedule endDate, plus resync container BT dates. When false, the schedule mutates alone and the caller is responsible for BT realignment. - `endDate` (string, optional) — New schedule end date (YYYY-MM-DD, inclusive). Only valid on the LAST schedule of the commitment (changes on earlier schedules would break contiguity). Must be ≥ the end of the latest commitment period on this schedule that has a non-voided invoice, and must align with a period boundary of every linked base BT's billing cadence. When composed with `startDateChange` on a single-schedule commitment, this value wins as the final absolute endDate (applied after startDateChange). - `startDateChange` (StartDateChangeDto, optional) — Optional start-date mutation. When present, only valid if the URL scheduleId is the FIRST schedule of the commitment (min sequence). `mode: extend` mutates only that schedule's startDate; blocked if it would cross a period that has a non-voided invoice. `mode: shift` translates every schedule and every commitment period by the delta; blocked entirely if any non-voided invoice exists anywhere on the commitment. When `cascadeBillingTerms=false`, both modes must align with linked base BT billing-period boundaries (the BT grid stays put), and the new startDate can't precede a linked BT's own start. When `cascadeBillingTerms=true`, the BT grid re-anchors to the schedule's new start, so the bound against the BT's own start is not enforced — except under `mode: shift`, where alignment against the old anchor is skipped entirely (the BT moves to match an arbitrary shift delta with no constraint on the resulting date); `mode: extend` with cascade=true still requires alignment to the BT's existing cadence grid. With cascade: `extend` moves linked base BTs' startDate + attached POBs' serviceStartDate to match the schedule's new start; `shift` translates every linked base BT and container BT (both edges) and every attached POB (both service edges) by the same calendar delta. - `commitmentInterval` (enum, optional) — New cadence for the schedule's commitment periods. Rejected if any period on this schedule already has a non-voided invoice, or if the schedule is multi-step (invariant #7: multi-step schedules must be full-duration). - Allowed values: `DAILY`, `WEEKLY`, `MONTHLY`, `QUARTERLY`, `SEMI_ANNUAL`, `YEARLY` - `prepaymentScheduleType` (enum, optional) — New prepayment schedule type. Rejected if any period on this schedule already has a non-voided invoice. - Allowed values: `FULL_UPFRONT`, `PER_COMMITMENT_PERIOD`, `SPLIT_ACROSS_BILLING_PERIODS` - `billingTermsToAdd` (list of map from string to list of string, optional) — Per-step billing term additions. Each element is \{ \[stepId]: btId\[] }. All steps must end with the same event-type set (invariant #6). Only base BT links (billingTermCommitmentType=null) can be added here. - `billingTermsToDelete` (list of map from string to list of string, optional) — Per-step billing term removals. Each element is \{ \[stepId]: btId\[] }. The BT must currently be linked as a base BT on that step. ## Response ### 200 Schedule patched - `payload` (PatchScheduleResponseDto, required) — Response payload, will be empty when success is false - `success` (boolean, required) — Boolean with true=success, false=failure - `message` (string, required) — Plain-text description of the result - `error` (IntegratorsApiError, optional) — json element with any error messages or warnings ## Errors ### 400 Bad Request Error Invoice gate, alignment, or structural constraint failed - `any` ### 403 Forbidden Error Commitments v2 is not enabled for this manufacturer - `any` ### 404 Not Found Error Schedule not found on commitment - `any` ## Types ### StartDateChangeDto - `mode` (enum, required) — `extend` mutates only the first schedule's startDate (moves it earlier, or shortens it up to — but not past — the first sent invoice). `shift` translates every schedule (and all commitment periods) by the delta between the current first-schedule startDate and the new startDate; blocked entirely if any invoice has been sent anywhere on the commitment. - Allowed values: `extend`, `shift` - `startDate` (string, required) — New startDate (YYYY-MM-DD, inclusive) for the first schedule. ### PatchScheduleResponseDto - `scheduleId` (string, required) — ID of the patched schedule ### IntegratorsApiError - `code` (double, required) — API response code - `message` (string, required) — API response message - `details` (IntegratorsApiErrorDetails, optional) — Additional details about the error ### IntegratorsApiErrorDetails Additional details about the error ## Examples **Request** ```json { "cascadeBillingTerms": false } ``` **Response** ```json { "payload": { "scheduleId": "string" }, "success": true, "message": "string", "error": { "code": 1.1, "message": "string", "details": {} } } ``` **SDK Code** ```python import requests url = "https://integrators.prod.api.tabsplatform.com/v3/contracts/123e4567-e89b-12d3-a456-426614174000/commitments/commitmentId/schedules/scheduleId" payload = { "cascadeBillingTerms": False } headers = { "Authorization": "", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = 'https://integrators.prod.api.tabsplatform.com/v3/contracts/123e4567-e89b-12d3-a456-426614174000/commitments/commitmentId/schedules/scheduleId'; const options = { method: 'PATCH', headers: {Authorization: '', 'Content-Type': 'application/json'}, body: '{"cascadeBillingTerms":false}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```go package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://integrators.prod.api.tabsplatform.com/v3/contracts/123e4567-e89b-12d3-a456-426614174000/commitments/commitmentId/schedules/scheduleId" payload := strings.NewReader("{\n \"cascadeBillingTerms\": false\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` ```ruby require 'uri' require 'net/http' url = URI("https://integrators.prod.api.tabsplatform.com/v3/contracts/123e4567-e89b-12d3-a456-426614174000/commitments/commitmentId/schedules/scheduleId") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = '' request["Content-Type"] = 'application/json' request.body = "{\n \"cascadeBillingTerms\": false\n}" response = http.request(request) puts response.read_body ``` ```java import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.patch("https://integrators.prod.api.tabsplatform.com/v3/contracts/123e4567-e89b-12d3-a456-426614174000/commitments/commitmentId/schedules/scheduleId") .header("Authorization", "") .header("Content-Type", "application/json") .body("{\n \"cascadeBillingTerms\": false\n}") .asString(); ``` ```php request('PATCH', 'https://integrators.prod.api.tabsplatform.com/v3/contracts/123e4567-e89b-12d3-a456-426614174000/commitments/commitmentId/schedules/scheduleId', [ 'body' => '{ "cascadeBillingTerms": false }', 'headers' => [ 'Authorization' => '', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` ```csharp using RestSharp; var client = new RestClient("https://integrators.prod.api.tabsplatform.com/v3/contracts/123e4567-e89b-12d3-a456-426614174000/commitments/commitmentId/schedules/scheduleId"); var request = new RestRequest(Method.PATCH); request.AddHeader("Authorization", ""); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"cascadeBillingTerms\": false\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` ```swift import Foundation let headers = [ "Authorization": "", "Content-Type": "application/json" ] let parameters = ["cascadeBillingTerms": false] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://integrators.prod.api.tabsplatform.com/v3/contracts/123e4567-e89b-12d3-a456-426614174000/commitments/commitmentId/schedules/scheduleId")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "PATCH" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ```