Create Commitments
If the customer has committed to a minimum spend or prepaid amount against their usage, create a commitment on the contract. Commitments are common in usage-based deals where the customer commits to a minimum spend in exchange for a discounted rate.
A commitment is made up of one or more schedules, and each schedule contains one or more steps:
- A schedule owns a date range, the commitment period interval, and the prepayment schedule type. Add more schedules to extend a commitment into new date ranges with different terms. Schedule date ranges must be contiguous — each
startDateis the day after the previous schedule’sendDate. - A step owns the commitment amount, the prepaid amount, and the billing terms it measures. Add more steps within a schedule to ramp the committed amount inside a single date range.
This guide walks through creating a commitment for a contract.
Step 1: Create the billing terms
Billing terms must exist before a commitment can reference them. A commitment doesn’t carry usage-pricing logic itself. It links to one or more billing terms (BTs) that already define how usage is priced (unit or flat billing, simple, tiered, or volume pricing) and which event type is being metered. The commitment layer only adds a target amount, and optionally turns on prepaid, true-up, or overage behavior, on top of BTs that already exist.
For a commitment, the BTs you create must be usage-based: set billingType: "UNIT" and an eventTypeId so the BT measures the event stream the commitment tracks. A commitment linked to a BT with no eventTypeId (for example, a flat recurring fee) has nothing to measure progress against, and isn’t a supported combination.
Practically, this means the workflow is always:
- Create the BTs (this section).
- Decide the commitment’s shape: one step, multiple steps, or multiple schedules (Step 2).
- Decide what else needs enabling: prepaid, true-up, or overage (Step 3).
- Create the commitment, referencing the BT IDs from step 1 (Step 4).
You cannot reverse steps 1 and 4: billingTermIds, billingTermsToAdd, and usageBillingTermId fields are validated against existing BT records at commitment-write time, and a commitment call referencing a BT ID that doesn’t exist (or belongs to a different contract or manufacturer) fails with 400: "Billing terms not found or deleted: <ids>."
To create the BTs:
Required fields: billingStartDate, isRecurring, interval, intervalFrequency, invoiceDateStrategy, netPaymentTerms, quantity, billingType, pricingType.
Key optional fields:
name: required unlessproductIdis set (then pulled from the product).productId: associate a product fromGET /v3/products; this populatesname,description,itemId, andclassIdfor any not explicitly set. Tabs recommends this for revenue-reporting accuracy.eventTypeId: the usage event type this BT meters. Required for any BT you intend to link to a commitment, since this is what lets the commitment’s usage tracking resolve to a concrete event stream.billingTermGroupId: join an existing BTG, or omit to create a new one.
Validation caveats:
intervalenum is exactlyNONE, DAY, MONTH, HOUR, YEAR, QUARTER, SEMI_MONTH, WEEK; anything else returns400:"interval must be one of the following values: ...".invoiceDateStrategyenum isFIRST_OF_PERIOD, LAST_OF_PERIOD, ARREARS, ADVANCED_DUE_START.billingTypeisUNITorFLATonly;pricingTypeisSIMPLE,TIERED, orVOLUME.- For
TIEREDorVOLUMEpricing, supply 2+pricing[]entries wheretieris 0-indexed and contiguous (0, 1, 2, and so on) andtierMinimumstarts at 0 and strictly increases; malformed tiers return400. - A successful call returns
201withBillingTermResponseDtowrapped in the standard{ payload, message, status }envelope (IntegratorsApiResponse). Grab the returned billing term ID: you need it forbillingTermIdswhen creating the commitment.
Repeat this call once per BT you need before creating the commitment. For example, create one per event type or product being metered, or a separate BT per usage tier if your pricing model calls for it.
Step 2: Decide between multiple steps and multiple schedules
Before creating the commitment, decide its shape. There are two independent axes of “more than one” here, and picking the wrong one produces the wrong billing behavior.
Multiple schedules: “step-up commitments” (independent calendar stages)
A schedule is a calendar-time phase of the commitment: its own startDate and endDate, its own commitmentInterval (billing cadence), and its own prepaymentScheduleType. Schedules on one commitment are ordered by sequence, and their dates must be contiguous (schedule N+1’s startDate picks up exactly where schedule N’s endDate left off, with no gaps and no overlaps). The sequence field itself does not have to stay gap-free over the commitment’s lifetime; deleted schedules and steps can leave holes in the raw sequence values. Only the dates are a hard invariant.
Use multiple schedules when the commitment’s terms change over calendar time: different cadence, different prepay strategy, or a different amount starting on a known future date. A classic example: year 1 is billed monthly with no prepay, and year 2 is fully prepaid upfront. This is what the user-facing docs call a “step-up” commitment: the customer’s commitment steps up into a new phase at a known date.
Multiple steps: “sequential commitments” (tiers within one schedule)
A step is a value tier within a single schedule’s date range. Steps in a schedule are consumed in order by sequence; once an earlier step’s capacity is exhausted, the next step’s pricing (enteredAt) takes over, both within the same start and end dates and the same billing cadence.
Use multiple steps when the commitment’s amount tiers within one continuous period, for example: the first 10k units this year are priced at Y, with both tiers covering the same 12-month window. This is what the user-facing docs call a “sequential” commitment: usage sequentially fills one tier, then rolls into the next.
The invariant that forces the choice
Steps within the same schedule must share the same commitmentUnitType and must resolve to the same event-type set (the set of event types implied by their linked base BTs). Changing the unit type always requires a new schedule; a step can’t change it without diverging from its siblings.
Swapping in BTs that meter a different event type does not necessarily require a new schedule, though: you can also do it on the existing schedule through the schedule-level billingTermsToAdd and billingTermsToDelete PATCH (see Add billing terms to steps within a schedule), as long as you add or remove the BT across every step in that schedule in the same call. That endpoint enforces the “same event-type set” invariant across all steps you touch at once, so a schedule-wide swap can stay on one schedule. A new schedule is only strictly required when you can’t, or don’t want to, touch every existing step’s BT set: for example, when you want the old event type to keep applying to earlier steps while only new steps track the new one. See Add/Edit a Step for step-level mechanics.
Also note a structural rule: multi-step schedules must be full-duration. You cannot set commitmentInterval on a schedule that has 2+ steps; the API rejects it with 400: "Multi-step schedules must be full-duration: omit commitmentInterval (interval/unit must be null)." Sub-interval slicing (for example, billing one tier monthly) only applies to single-step schedules.
Step 3: Decide what else to enable: prepaid, true-up, and overage
Each step can independently turn on:
- Prepaid (
prepaidEnabled+prepaidValue): the customer pays some or all of the commitment value upfront rather than as usage accrues. When enabled,prepaidValuemust be a positive number (400:"prepaidEnabled=true requires a positive prepaidValue."if omitted or ≤ 0); when disabled,prepaidValuemust be omitted or0(400:"prepaidEnabled=false is inconsistent with prepaidValue=X."otherwise). A prepaid step additionally requires its schedule to carry aprepaymentScheduleType; enabling prepaid on a step whose schedule has none returns400:"schedule has no prepaidScheduleType set. Set the schedule's prepayment behavior (FULL_UPFRONT / PER_COMMITMENT_PERIOD / SPLIT_ACROSS_BILLING_PERIODS) before adding a prepaid step."Decide the schedule’sprepaymentScheduleTypefirst if any of its steps will be prepaid. - True-up (
trueUpBehavior, commitment-level only, valuesDEFAULTorNEVER): what happens if the customer under-uses the commitment.DEFAULTbills the shortfall (trues up unmet commitment);NEVERforgives it silently. - Overage (
overageBillingTermsat step creation): pricing applied once usage exceeds the step’s value. Each overage entry references an existing base usage BT throughusageBillingTermId; the overage BT and its performance obligation are created server-side. Supply multiple entries for tiered overage on a step. Omit the field entirely if a BT needs no overage: sending an entry with an emptyoveragePricingsarray returns400:"overagePricings must include at least 1 tier when this entry is present". - Price priority (
pricePriority,LOWorHIGH): when multiple products or BTs are linked, which one’s price wins in ambiguous cases.
None of these are mutually exclusive, and all but trueUpBehavior are set per-step rather than per-commitment. If you’re building a multi-step or multi-schedule commitment, decide prepaid and overage per step, not once for the whole thing.
Step 4: Create the commitment
Create the commitment through the nested endpoint below, with explicit schedules and steps up front. This writes directly into the UsageCommitmentSchedule and UsageCommitmentStep tables, so the commitment is fully editable afterward through Add/Edit a Schedule and Add/Edit a Step.
Structural requirements: at least 1 commitment, each with at least 1 schedule ("At least 1 schedule is required per commitment"), and each schedule with at least 1 step ("Each schedule must have at least 1 step"). sequence on both schedules and steps is caller-supplied at creation time and must be dense and 0-indexed (0..N-1). trueUpBehavior is DEFAULT (trues up unmet commitment) or NEVER (forgives it): note the valid values are DEFAULT or NEVER, not TRUE_UP or NEVER.
A successful call returns 201 with { payload: { success: true, commitmentIds: [...] } }.
Caveats:
- The call returns
400if a referenced billing term is locked down (already invoiced) or otherwise ineligible for commitment linkage, or404if the contract doesn’t exist for this manufacturer. - The API treats dates you send as inclusive; internally it stores them exclusive (
endDate+1 day, throughtoExclusiveEndDate). You never see the exclusive form: always send and receive inclusive dates. - A non-prepaid step whose
commitmentUnitTypeisUNITScan only track one event type across itsbillingTermIds, or the call returns400:"non-prepaid UNITS steps can only have one associated event type; candidate billing terms map to N distinct event types."PrepaidUNITSsteps are exempt (a prepaid commitment can bundle usage across multiple event types). - Two of a step’s billing terms that share an event type must not have overlapping date ranges, since usage would double-count, or the call returns
400:"billing terms X and Y share event type Z and have overlapping date ranges..."
Common errors and troubleshooting
Error codes referenced in this guide
201: created successfully (POST /v3/contracts/:id/commitments,POST /v3/contracts/:id/billing-terms)400: validation error (payload shape, BT lockdown, structural or invariant violation)404: contract not found for this manufacturer (includes cross-tenant mismatches)500: internal server error

