> For the complete documentation index, see [llms.txt](https://docs.shortcutco.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.shortcutco.com/developers/resources/changelog.md).

# Changelog

New endpoints, fields, tools, and changes to the Shortcut API and MCP server.

Additions within `v1` appear here as they ship. A change that would break a working client goes to a new version instead; see [Versioning](/developers/concepts/conventions.md#base-url-and-versions).

## 2026-10-18

Reminder retries and paused webhooks.

* A repeated `POST /v1/invoices/{id}/remind` or `POST /v1/estimates/{id}/remind` whose first attempt is still sending now gets a retryable `409 reminder_in_progress` with `Retry-After`, instead of `meta.alreadyReminded: true` for a reminder that never went out. If the first attempt stopped before finishing, the retry sends the reminder. See [reminder\_in\_progress](/developers/concepts/errors.md#reminder_in_progress).
* A webhook resumed while events were arriving sends every event it held. Before, an event that arrived during the resume could stay held.

The OpenAPI description.

* `https://api.shortcutco.com/v1/openapi.json` defines each object once under `components.schemas` (such as `Customer` and `CustomerWithProperties`) and points every endpoint at it with `$ref`, with shared error responses under `components.responses`. Generated clients get one type per object instead of one per endpoint. The contract itself is unchanged.
* Answers about one object now declare their optional `meta` (such as `alreadyReminded` or `effects`), which they already sent. A client that rejected unknown top-level keys accepts them now.
* Every endpoint carries curl, Node.js, and Python samples in `x-codeSamples`, and request and response examples.
* The external upserts declare both answers they send: `200` when your id already existed and `201` when the request created the record. `POST /v1/invoices/{id}/payments` declares the `200` a repeated request gets, with `meta.alreadyRecorded`.
* Each object has a page in the reference, such as [The customer object](/developers/api-reference/reference/objects/customer.md).

## 2026-10-17

Sign in to connect AI apps.

* Claude and ChatGPT connect to the MCP server by signing in to Shortcut: a company admin approves read access, and no token is copied. See [Connect Claude](/developers/mcp/connect-claude.md#sign-in-from-claude) and [Connect ChatGPT](/developers/mcp/connect-chatgpt.md).
* Signed-in apps appear in **Settings → API & integrations → Connected apps**, where an admin disconnects them.
* OAuth 2.1 discovery at `/.well-known/oauth-authorization-server`, with PKCE (S256), client ID metadata documents, dynamic client registration, and token revocation (RFC 7009). OAuth access tokens work on the MCP server only; the REST API keeps using API tokens.
* `automations:trigger` now covers your **Automations** rules too. Without it, records the API creates or changes, and the visits an approved estimate schedules, start none of your Automations rules or the new-lead welcome automation. Sending an estimate or invoice (`estimates:send`, `invoices:send`) always runs its delivery automation, including any steps you added to it. A job paused until a date resumes on that date like any paused job, and visits it schedules then run your rules. Before, only the new-lead welcome, new-customer, job-scheduled, job-rescheduled, and job-canceled automations depended on the scope. See [automations:trigger](/developers/concepts/scopes.md#automationstrigger).

Invoice sends and offline payments.

* `POST /v1/invoices/{id}/send` sends a draft by email as the app does; a draft for an autopay customer is refused. `POST /v1/invoices/{id}/remind` sends a payment reminder by email and text, at most once per invoice in ten minutes. Both need `invoices:send` and `invoices:read`.
* `POST /v1/invoices/{id}/void` voids an unpaid or overdue invoice with the app's rules, with a reason recorded on the customer's notes (`invoices:write`).
* `POST /v1/invoices/{id}/payments` records a cash, check, or other offline payment for the invoice's full total (`payments:write`); `POST /v1/payments/{id}/reverse` undoes one (`payments:write` and `invoices:read`). No endpoint charges a card.
* MCP tools `send_invoice`, `remind_invoice`, `void_invoice`, `record_offline_payment`, and `reverse_payment`.
* Error codes `autopay_charge_required`, `amount_mismatch`, `no_recipient`, `token_creator_unavailable`, `invoice_recently_reminded`, and `dependency_unavailable`. See [Errors](/developers/concepts/errors.md).

Customers, properties, tags, and custom fields.

* `POST /v1/customers` with the first property inline, optional email, and optional `externalReference`; `PATCH /v1/customers/{id}` for contact details; `POST /v1/customers/{id}/deactivate` (pauses the customer's jobs) and `POST /v1/customers/{id}/reactivate` (with `resumeJobs`, which needs `jobs:write`).
* `GET /v1/customers/{id}/properties` with `updatedSince`; `POST /v1/customers/{id}/properties`; `GET /v1/properties/{id}`; `PATCH /v1/properties/{id}`, with `confirmClearPropertyMap` for address moves that clear the property map.
* `POST /v1/tags`, `PATCH /v1/tags/{id}`, and `DELETE /v1/tags/{id}`; `GET /v1/customers/{id}/tags` and `PUT /v1/customers/{id}/tags`, which replaces the whole list.
* `GET /v1/custom-fields` (`custom_fields:read`); `GET /v1/customers/{id}/custom-fields` and `PUT /v1/customers/{id}/custom-fields`.
* External references: `GET` and `PUT /v1/customers/external/{source}/{externalId}` and `/v1/properties/external/{source}/{externalId}` for lookup and upsert; `PUT` and `DELETE /v1/customers/{id}/external-references/{source}` and `/v1/properties/{id}/external-references/{source}` to link and unlink; the `externalSource` and `externalId` filter on `GET /v1/customers`. Customers and properties carry `externalReferences`. See [Sync](/developers/concepts/sync.md#external-references).
* Attaching or removing a tag, deleting a worn tag, and changing a custom-field value now change the customer's `updatedAt`.
* MCP tools `create_customer`, `update_customer`, `deactivate_customer`, `reactivate_customer`, `add_property`, `update_property`, `list_tags`, `create_tag`, `rename_tag`, `delete_tag`, `set_customer_tags`, `list_custom_fields`, `get_customer_custom_fields`, and `set_customer_custom_fields`.
* Error codes `email_in_use`, `external_reference_exists`, `external_reference_customer_mismatch`, `external_reference_changed`, `customer_not_inactive`, `jobs_not_resumable`, and `transaction_timeout`. See [Errors](/developers/concepts/errors.md).

Webhooks.

* Webhook subscriptions: a signed HTTPS `POST` to your endpoint when a customer, lead, estimate, job, visit, invoice, or payment changes. 28 event types in 7 families, from `customer.created` to `payment.reversed`; subscribing to a family needs its read scope. See [Webhooks](/developers/webhooks/overview.md) and [Events](/developers/webhooks/events.md).
* `GET /v1/webhooks`, `POST /v1/webhooks`, `GET /v1/webhooks/{id}`, `PATCH /v1/webhooks/{id}` (including pausing and resuming), `DELETE /v1/webhooks/{id}`, `POST /v1/webhooks/{id}/rotate-secret`, `POST /v1/webhooks/{id}/test`, `GET /v1/webhooks/{id}/deliveries`, and `POST /v1/webhooks/{id}/deliveries/{deliveryId}/retry`, with the `webhooks:manage` scope.
* `Shortcut-Signature` HMAC-SHA256 signatures with a five-minute tolerance and a 24-hour overlap after rotation. See [Verify signatures](/developers/webhooks/verify-signatures.md).
* Retries over about 15 hours, a deliveries list kept for 30 days, and automatic turn-off after 50 failed attempts in a row. See [Retries and monitoring](/developers/webhooks/retries-and-monitoring.md).
* Error codes `invalid_webhook_url`, `webhook_limit_reached`, `delivery_not_retryable`, `webhook_not_active`, and `webhook_signing_unavailable`. See [Errors](/developers/concepts/errors.md).

Services, products, crews, and staff.

* `GET /v1/services` with `status`, `serviceType`, and `updatedSince`; `POST /v1/services`; `GET /v1/services/{id}`; `PATCH /v1/services/{id}`; `POST /v1/services/{id}/deactivate` (with `force`) and `/reactivate`. Chemical services are read-only.
* `GET /v1/products` with `status` and `updatedSince`; `POST /v1/products`; `GET /v1/products/{id}`; `PATCH /v1/products/{id}`, including `archived`.
* `GET /v1/teams` with `archived` and `updatedSince`, and `GET /v1/teams/{id}`, with each crew's active members.
* `GET /v1/users` with `role`, `status`, `teamId`, and `updatedSince`, and `GET /v1/users/{id}`.
* MCP tools `list_services`, `get_service`, `create_service`, `update_service`, `deactivate_service`, `reactivate_service`, `list_products`, `get_product`, `create_product`, `update_product`, `list_teams`, `get_team`, `list_users`, and `get_user`.
* Error code `feature_unavailable`. See [Errors](/developers/concepts/errors.md#feature_unavailable).

Leads, estimates, and jobs.

* `GET /v1/leads` with `status`, `lifecycleStage`, `source`, and `updatedSince`; `GET /v1/leads/{id}`; `PATCH /v1/leads/{id}` for contact details, address, hours estimate, and square footage, with `confirmClearPropertyMap` for address moves that clear the property map; `POST /v1/leads/{id}/dismiss` and `POST /v1/leads/{id}/restore`. Leads carry `estimatedHours` and `sqFootage`.
* `GET /v1/estimates` with `status`, `customerId`, `leadId`, and `updatedSince`; `GET /v1/estimates/{id}` with lines, price options, and products.
* `GET /v1/jobs` with `customerId`, `propertyId`, `status`, `teamId`, and `updatedSince`; `POST /v1/jobs`; `GET /v1/jobs/{id}`; `PATCH /v1/jobs/{id}`; `POST /v1/jobs/{id}/schedule`, `/pause`, `/resume`, and `/cancel`; `GET /v1/jobs/{id}/visits`.
* MCP tools `list_leads`, `get_lead`, `update_lead`, `dismiss_lead`, `restore_lead`, `list_estimates`, `get_estimate`, `list_jobs`, `get_job`, `list_job_visits`, `create_jobs`, `schedule_job`, `update_job`, `pause_job`, `resume_job`, and `cancel_job`.
* Error codes `state_conflict`, `rule_violation`, `lead_is_customer`, and `property_map_would_clear`. See [Errors](/developers/concepts/errors.md).

Visits.

* `POST /v1/visits/{id}/reschedule` with `date`, `scope` (`this_only` or `this_and_future`), and `placement`; `POST /v1/visits/{id}/assign` with `teamId`; `POST /v1/visits/{id}/cancel` and `POST /v1/visits/{id}/skip`, which close a visit through the same path as Dispatch (skip sends no job-canceled notice). A visit the crew has started is never moved.
* `POST /v1/visits/{id}/complete` with the `visits:complete` and `visits:read` scopes: completes the visit as the app does; billing follows after the app's five-minute undo window, creating the invoice, queuing its delivery, and charging autopay when the customer has it on. Returns `billing`, `holdId`, `finalizeAt`, `invoiceId`, and `effects`; `completeStop=true` completes the stop's other open services on one invoice. See [Scopes](/developers/concepts/scopes.md#visitscomplete).
* Visits carry `invoiceId`.
* MCP tools `reschedule_visit`, `assign_visit`, `cancel_visit`, `skip_visit`, and `complete_visit`.

Estimate writes, approval, and sending.

* `POST /v1/estimates` creates a draft for a lead from catalog services, and the app prices it. `PATCH /v1/estimates/{id}` changes a draft's message, property, or lines.
* `POST /v1/estimates/{id}/void` voids an estimate. `POST /v1/estimates/{id}/approve` approves it on the customer's behalf and creates its jobs, with `meta.alreadyApproved` and `meta.createdJobIds`.
* `POST /v1/estimates/{id}/send` and `POST /v1/estimates/{id}/remind` need `estimates:send`. A reminder is limited to one per estimate every ten minutes and is never sent twice for one `Idempotency-Key`.
* Leads created with `POST /v1/leads` or `create_lead`, and the lead rows of customers created with `POST /v1/customers`, now have `source` `api`. Earlier ones keep `manual`.
* MCP tools `create_estimate`, `update_estimate`, `void_estimate`, `approve_estimate`, `send_estimate`, and `remind_estimate`.
* Error codes `service_not_supported`, `estimate_expired`, `estimate_not_approvable`, `estimate_not_sendable`, `customer_comms_suppressed`, `reminder_not_sent`, `estimate_recently_reminded`, and `follow_up_not_queued`. See [Errors](/developers/concepts/errors.md).

Invoices and payments.

* `GET /v1/invoices` with `status`, `customerId`, `dueBefore`, and `updatedSince`; `GET /v1/invoices/{id}` with the lines the customer sees. Invoices carry `kind`, `status`, `paymentActivity`, amounts in US dollars, `dueDate` as printed on the invoice, and `dueAt`.
* `GET /v1/payments` with `invoiceId`, `customerId`, and `createdSince`; `GET /v1/payments/{id}`. Payments carry `method`, `reference`, and `refundedAmount`.
* MCP tools `list_invoices`, `get_invoice`, `list_payments`, and `get_payment`, with the `invoices:read` and `payments:read` scopes.

## 2026-10-16

The Shortcut Platform API, version 1.

**Tokens and access**

* Workspace API tokens, created by company admins in **Settings → API & integrations**, with per-resource scopes and the **Read everything** and **Standard integration** presets. See [Scopes](/developers/concepts/scopes.md).
* `GET /v1/me`: the token, its scopes, its workspace with timezone and today's date, and the current rate-limit window.
* `GET /v1/openapi.json`: the OpenAPI 3.1 description, public.

**REST endpoints**

* `GET /v1/customers` with `q`, `status`, `tagId`, and `updatedSince`; `GET /v1/customers/{id}` with the customer's properties.
* `GET /v1/tags` with `updatedSince`; `GET /v1/tags/{id}`.
* `GET /v1/visits` with `from`, `to`, `teamId`, `status`, `customerId`, `jobId`, and `updatedSince`; `GET /v1/visits/{id}`. Visits carry `effectiveTeamId` and `routePosition`.
* `POST /v1/leads`: create a lead that behaves like one from the website form, with `Idempotency-Key` support.

**MCP server**

* `https://api.shortcutco.com/mcp`, Streamable HTTP, protocol versions `2025-11-25` and `2025-06-18`, bearer-token authentication.
* Tools: `find_customer`, `get_customer`, `get_schedule`, `list_visits`, `get_visit`, `create_lead`, and `explain_scopes`. See [MCP overview](/developers/mcp/overview.md).

**Conventions**

* Cursor pagination, incremental sync with `updatedSince`, idempotency keys, rate-limit headers, and structured errors with a link to each code. See [Conventions](/developers/concepts/conventions.md).
