# Invoices

> Update an invoice issue date, with the Stripe expectations reviewed first.

Source: https://metrocli.com/docs/guides/invoices/ · Docs index: https://metrocli.com/llms.txt

## Goal

Move a draft invoice's issue date from 1 December to 5 December 2026, without surprising the customer in Stripe.

Metronome changes an issue date through `POST /v1/contracts/updateInvoiceIssueDate`. It works only on `DRAFT` invoices, and the new date must come before the contract's end. See [Invoices](/docs/concepts/invoices).

> **Preview only in this release.** metro validates and previews this change, and builds the guarded read for the readback. It does not apply it yet: the endpoint isn't on the sandbox write allowlist, and the shape's apply mode is blocked. Make the change where your team makes it today, then read it back with metro.

## Preview

Write the input. Every field is required, and the evidence flags say what you've already checked.

```json
{
  "customerId": "00000000-0000-4000-8000-000000000001",
  "contractId": "00000000-0000-4000-8000-000000000002",
  "invoiceId": "00000000-0000-4000-8000-000000000003",
  "currentInvoiceStatus": "DRAFT",
  "currentIssueDate": "2026-12-01T00:00:00.000Z",
  "targetIssueDate": "2026-12-05T00:00:00.000Z",
  "contractHasNoEndDate": true,
  "invoiceReadbackVerified": true,
  "contractEndVerified": true,
  "billingProvider": { "verified": true },
  "stripeBehavior": "remain_draft_for_manual_review",
  "verificationPlan": { "invoiceReadback": true, "billingProviderReadback": true, "stripeDeliveryReview": true },
  "remediationPlan": "Move the issue date back with the same endpoint while the invoice is still DRAFT."
}
```

```bash
metro validate --shape invoice-issue-date-update --file issue-date.json
metro invoice issue-date preview --file issue-date.json --sandbox
```

```text
✓ Validation passed for invoice-issue-date-update.
Why: The input matches the reviewed shape rules and guardrails.

Preview built for invoice-issue-date-update on sandbox.
Payload hash: sha256:9e12f2fc713df1919e5f862a4d0f5ad8a5352f1d94626583a0431a4c02712b6c
Actions: 1
Apply supported: no
```

`stripeBehavior` must be one of `defer_until_new_issue_date`, `remain_draft_for_manual_review` or `no_stripe_delivery_expected`. Anything else fails with `MTR-INV-004`. That's the point of the shape: you decide what Stripe should see before anything moves.

## Confirm

Show the human the invoice, the old and new issue dates, the Stripe behavior and the hash. Check the remediation plan reads as something you could actually do. A finalized invoice can't be moved, so confirm the status is still `DRAFT` on the day.

## Apply

Not in metro yet. Make the change in Metronome, with the reviewed preview as the change record. When metro ships apply for this shape, this step becomes the same `--confirm-hash` and `--apply` pair as every other guide.

## Readback

Read the invoice back through the guarded read chain. `invoices.get` is on the live read allowlist.

```bash
metro invoice inspect --invoice-id 00000000-0000-4000-8000-000000000003 --sandbox --plan
echo '{"invoice_id":"00000000-0000-4000-8000-000000000003"}' > get-invoice.json
metro api read-plan invoices.get --file get-invoice.json --sandbox --json > read-plan.json
metro api read-gate template --read-plan read-plan.json --json > read-gate.json
# fill in and review the gate: status, tenant profile, key env and fingerprint
metro api read-gate validate --file read-gate.json
metro api read invoices.get --file get-invoice.json --sandbox --read-gate read-gate.json \
  --confirm-live-read I_UNDERSTAND_THIS_WILL_READ_LIVE_METRONOME --json
```

Compare expected and actual yourself, and report both:

| Field | Expected | Actual |
|---|---|---|
| status | `DRAFT` | from the read |
| issue date | `2026-12-05T00:00:00.000Z` | from the read |
| Stripe invoice | per `stripeBehavior` | from your billing provider |
