# contracts.reconcile_usage

Reconcile a vendor invoice or statement to the usage estimates of one vendor contract: clear the accrual, post the difference and spread it over the customers, people and teams the usage served.

## What it does

Record one vendor document against a contract's usage estimates. source.kind is invoice (creates one payable claim for the lines' net) or statement (the vendor's own cost figure, no payable: it trues the accrual up, and final closes the period). Each line has a lineKey and amount (the declared price, minor units) and may give credit (the vendor credit applied to it) and taxAmount (the invoice's stated tax in minor units; signed on corrections).

Stated supplier tax wins over derivation at the contract rate; the stored tax amount is the stated figure, computedAmount retains the signed derived figure, and attention.usageReview tax_differs names both (a one-unit difference is not flagged when two or more supplier-tax lines state tax). Self-assessed tax (reverse_charge, imported_services) keeps the derived figure; the vendor's taxAmount stays on the line as evidence.

A tax-only correction (amount 0, taxAmount given; for self-assessed tax the business's own figure) records tax after a final credit-paid statement; on a period that already posted tax it is recorded and flagged tax_differs. On an invoice the right's taxCode and taxTreatment determine tax: supplier tax adds to the same payable, non-recoverable tax joins attributed cost, inclusive input tax comes out of cost, and self-assessed tax posts separately. Observations and statements post no tax. The result retains the invoice tax basis and allocation taxShare.

A credit lowers the taxable base for reduces_tax_base lots, and applied credit no lot can fund lowers it unless the lots this right can draw (open, or drawn for the period) all froze another tax position; tax-inclusive credit pools and includes_tax lots on taxed rights are refused.

A metered line names the right's activityKey and one usage period of its meter, and may give quantity, the period's total metered quantity: the vendor plan's price for it is compared with the amount, and a difference beyond the meter's rounding tolerance flags the contract attention.priceDiffers since that date (a later matching bill or an amendment under which it computes clears it).

For each metered line the accrual is cleared, the gross difference posts to the right's expense account, spread over the period's attribution by largest remainder in each attribution's function, and the credit difference draws the right's credit pool in its order (a live lot pays even when the granted lot that served the period has lapsed) or returns credit to the lots the period drew.

Credit no lot can pay (the live lots hold too little, or there is no pool) is recorded as unfunded: an invoice or final statement nets the expense to the vendor's figure, an interim statement keeps it accrued as owed until the bill; it flags attention.usageReview credit_unfunded. A line other than a correction that gives no credit for a period whose granted lot has lapsed by this date flags credit_expired, since the books cannot tell what credit the vendor applied.

A line on a period already billed must set correction and posts at this document's date; a line with no estimates is unestimated and posts whole (a measured seat meter splits it by active seats per team). handledElsewhere lines (plan fees, seats recorded with contracts.record; a measured seat line for exactly a service period contracts.record already billed, at the same quantity when both name one, is kept so and flagged billed_twice; one at another seat count posts and flags seat_count_differs with both counts) and lines with no activityKey (unmatched) post nothing; when invoiceTotal is given every commercial line, handled or not, must sum to it (amount less credit plus stated or derived supplier tax); do not repeat derived tax as a separate line, and give handledElsewhere and unmatched amounts including supplier tax, or state that tax separately with taxAmount; these lines post nothing.

Possible shared-invoice overlap with a partial-period or quantity-adjustment bill posts and raises invoice_overlap. A line overlapping an open accrual elsewhere in its replacement family posts and raises accrual_overlap; it does not release another contract's accrual. These review items name relatedContractId. To replace a reissued bill explicitly, give replacesBillId (an ordinary occurrenceId or usage reconciliationId), a fresh source fact, the same vendor party and currency, and a date at or after the old phases: reversal and new recording commit atomically.

Existing payment value stays as vendor credit applied to the replacement, with any excess credit identified in result.replacement. Usage invoices with later period changes or credit-lot movements need their dependencies corrected first. Otherwise decide whether both charges stand and resolve the review with contracts.resolve_usage_review.

The result lists unbilledEstimates: earlier periods still carrying estimates no line billed, which stay accrued until a line (amount 0 reverses one) bills them, and usageReviewItems: the attention.usageReview items this document raised, which contracts.resolve_usage_review resolves.

## Before you send it

An authorized OAuth connection may call it, including a headless client. Effective membership, application grant and token permissions still apply. Describe `contracts.reconcile_usage` through `GET /v1/catalog/commands/{name}` before acting.

The envelope may reference a registered source document of kind `source_document`; this is separate from any evidence required by the input.

## Inputs

Put these fields inside the envelope's `input` object. The outer envelope names the command, a stable `idempotency_key` and `effective_at`; [request and recovery rules](/docs/api/) explain those separately. Use exact minor-unit integer strings for monetary fields. Take existing IDs from prior reads or command results; choose a new identity only where the command asks for one.

Required means required within its containing object; an optional parent can be omitted.

| Field | Type | Required | Meaning and accepted values |
|---|---|---|---|
| `contractId` | string | Yes |  Minimum length: `1`. Example: `"ctr_example"`. |
| `sourceFactId` | string | Yes |  Minimum length: `1`. Example: `"invoice:doc_example"`. |
| `replacesBillId` | string | No |  Minimum length: `1`. |
| `effectiveAt` | string | Yes |  Format: date-time. Example: `"2026-10-15T00:00:00Z"`. |
| `source` | object | Yes |   |
| `source.kind` | string | Yes |  Choose `"invoice"`, `"statement"`. Example: `"invoice"`. |
| `source.documentId` | string | No |  Minimum length: `1`. |
| `source.reference` | string | No |  Minimum length: `1`. Example: `"INV-0042"`. |
| `final` | boolean | No |  Must be `true`. |
| `dueDate` | string | No |  Format: date. Example: `"2026-10-15"`. |
| `invoiceTotal` | string | No |  Pattern: `"^(0\|-?[1-9][0-9]*)$"`. Example: `"6308"`. |
| `lines` | array | Yes |  Items: object. Minimum items: `1`. Maximum items: `200`. |
| `lines[].lineKey` | string | Yes |  Minimum length: `1`. Maximum length: `64`. Example: `"3"`. |
| `lines[].description` | string | No |  Minimum length: `1`. Maximum length: `512`. Example: `"Actions Linux, September usage beyond 3,000 included minutes"`. |
| `lines[].activityKey` | string | No |  Minimum length: `1`. Example: `"actions_linux"`. |
| `lines[].period` | object | No |   |
| `lines[].period.from` | string | Yes |  Format: date-time. Example: `"2026-09-01T00:00:00Z"`. |
| `lines[].period.through` | string | Yes |  Format: date-time. Example: `"2026-10-01T00:00:00Z"`. |
| `lines[].quantity` | string | No |  Pattern: `"^(0\|[1-9][0-9]*)$"`. Example: `"4013"`. |
| `lines[].amount` | string | Yes |  Pattern: `"^(0\|-?[1-9][0-9]*)$"`. Example: `"608"`. |
| `lines[].taxAmount` | string | No |  Pattern: `"^(0\|-?[1-9][0-9]*)$"`. |
| `lines[].credit` | string | No |  Pattern: `"^(0\|[1-9][0-9]*)$"`. |
| `lines[].correction` | boolean | No |  Must be `true`. |
| `lines[].handledElsewhere` | boolean | No |  Must be `true`. |
| `evidence` | object | Yes |   |
| `evidence.billing` | array | Yes |  Items: object. Minimum items: `1`. Maximum items: `20`. |
| `evidence.billing[].kind` | string | Yes |  Choose `"tap_message"`, `"x402_receipt"`, `"chain_tx"`, `"signed_doc"`, `"stripe_object"`, `"other"`. Example: `"other"`. |
| `evidence.billing[].ref` | string | Yes |  Minimum length: `1`. Example: `"doc_example"`. |
| `evidence.billing[].signer` | string | No |  Minimum length: `1`. |

## After acceptance

When the command emits events, its documented effects and receipt are recorded in the command transaction. The response returns `commandId`, `replayed`, the command-specific `result` below and emitted `events` with their IDs and CIDs. A command is not automatically a cash movement or revenue recognition: use the behavior above to determine what this command records.

Inspect `result` and the affected records or reports before continuing. Save returned identifiers for later calls. Fetch `GET /v1/commands/{id}` with `commandId` to recover the accepted receipt; retry the same intent with the same idempotency key if the response was lost. Some commands can succeed with `events: []` and return a transient result and `commandId` without persisting a receipt. A lookup of that ID can return null; retain the returned result and verify the affected record. Retrying can re-evaluate the current state rather than replay a stored result. A domain `no_change` is a separate success outcome with no persisted receipt.

### Result fields

Required means required within its containing object; an optional parent can be omitted.

| Field | Type | Required | Meaning and accepted values |
|---|---|---|---|
| `replacement` | object | No |   |
| `replacement.billId` | string | No |   |
| `replacement.reversedPhases` | array | No |  Items: string. |
| `replacement.creditClaimId` | string | No |   |
| `replacement.creditAmount` | string | No |   |
| `replacement.appliedCredit` | string | No |   |
| `replacement.remainingCredit` | string | No |   |


[All commands](/docs/command-reference/) · [Operation and errors](/docs/api-reference/operations/commands-execute/) · [Reusable schemas](/docs/api-reference/components/)

Keep credentials out of prompts; rehearse writes only in a disposable sandbox.

## Exact request schema


```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name": {
      "const": "contracts.reconcile_usage"
    },
    "input": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "contractId",
        "sourceFactId",
        "effectiveAt",
        "source",
        "lines",
        "evidence"
      ],
      "properties": {
        "contractId": {
          "type": "string",
          "minLength": 1
        },
        "sourceFactId": {
          "type": "string",
          "minLength": 1
        },
        "replacesBillId": {
          "type": "string",
          "minLength": 1
        },
        "effectiveAt": {
          "type": "string",
          "format": "date-time"
        },
        "source": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind"
          ],
          "properties": {
            "kind": {
              "enum": [
                "invoice",
                "statement"
              ]
            },
            "documentId": {
              "type": "string",
              "minLength": 1
            },
            "reference": {
              "type": "string",
              "minLength": 1
            }
          }
        },
        "final": {
          "const": true
        },
        "dueDate": {
          "type": "string",
          "format": "date"
        },
        "invoiceTotal": {
          "type": "string",
          "pattern": "^(0|-?[1-9][0-9]*)$"
        },
        "lines": {
          "type": "array",
          "minItems": 1,
          "maxItems": 200,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "lineKey",
              "amount"
            ],
            "properties": {
              "lineKey": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64
              },
              "description": {
                "type": "string",
                "minLength": 1,
                "maxLength": 512
              },
              "activityKey": {
                "type": "string",
                "minLength": 1
              },
              "period": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "from",
                  "through"
                ],
                "properties": {
                  "from": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "through": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              },
              "quantity": {
                "type": "string",
                "pattern": "^(0|[1-9][0-9]*)$"
              },
              "amount": {
                "type": "string",
                "pattern": "^(0|-?[1-9][0-9]*)$"
              },
              "taxAmount": {
                "type": "string",
                "pattern": "^(0|-?[1-9][0-9]*)$"
              },
              "credit": {
                "type": "string",
                "pattern": "^(0|[1-9][0-9]*)$"
              },
              "correction": {
                "const": true
              },
              "handledElsewhere": {
                "const": true
              }
            }
          }
        },
        "evidence": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "billing"
          ],
          "properties": {
            "billing": {
              "type": "array",
              "minItems": 1,
              "maxItems": 20,
              "items": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "kind",
                  "ref"
                ],
                "properties": {
                  "kind": {
                    "enum": [
                      "tap_message",
                      "x402_receipt",
                      "chain_tx",
                      "signed_doc",
                      "stripe_object",
                      "other"
                    ]
                  },
                  "ref": {
                    "type": "string",
                    "minLength": 1
                  },
                  "signer": {
                    "type": "string",
                    "minLength": 1
                  }
                }
              }
            }
          }
        }
      }
    },
    "idempotency_key": {
      "type": "string",
      "minLength": 1,
      "maxLength": 256
    },
    "effective_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "source_document_id": {
      "description": "A registered document of kind source_document that caused this command.",
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "name",
    "input",
    "idempotency_key",
    "effective_at"
  ],
  "additionalProperties": false
}
```

## Accepted command receipt


```json
{
  "type": "object",
  "required": [
    "commandId",
    "replayed",
    "result",
    "events"
  ],
  "properties": {
    "commandId": {
      "type": "string"
    },
    "replayed": {
      "type": "boolean"
    },
    "imported": {
      "const": true,
      "description": "The command's events are history from before the business joined Economico, recorded as an import: free of monthly events."
    },
    "result": {
      "type": "object",
      "properties": {
        "replacement": {
          "type": "object",
          "properties": {
            "billId": {
              "type": "string"
            },
            "reversedPhases": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "creditClaimId": {
              "type": "string"
            },
            "creditAmount": {
              "type": "string"
            },
            "appliedCredit": {
              "type": "string"
            },
            "remainingCredit": {
              "type": "string"
            }
          }
        }
      }
    },
    "events": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "cid": {
            "type": "string"
          }
        }
      }
    }
  }
}
```

## Example request


```json
{
  "name": "contracts.reconcile_usage",
  "input": {
    "contractId": "ctr_example",
    "sourceFactId": "invoice:doc_example",
    "effectiveAt": "2026-10-15T00:00:00Z",
    "source": {
      "kind": "invoice",
      "reference": "INV-0042"
    },
    "dueDate": "2026-10-15",
    "invoiceTotal": "6308",
    "lines": [
      {
        "lineKey": "3",
        "description": "Actions Linux, September usage beyond 3,000 included minutes",
        "activityKey": "actions_linux",
        "period": {
          "from": "2026-09-01T00:00:00Z",
          "through": "2026-10-01T00:00:00Z"
        },
        "quantity": "4013",
        "amount": "608"
      },
      {
        "lineKey": "1",
        "description": "Copilot Business seats",
        "amount": "5700",
        "handledElsewhere": true
      }
    ],
    "evidence": {
      "billing": [
        {
          "kind": "other",
          "ref": "doc_example"
        }
      ]
    }
  },
  "effective_at": "2026-09-01T00:00:00Z",
  "idempotency_key": "contracts.reconcile_usage-example-0"
}
```


