KintsugiKintsugi
API reference / Changelog / 2026

API changelog: 2026

Every change to the Kintsugi API in 2026, newest first. For the latest changes and every release, see the API changelog.

2026-10-05

Breaking changes
Limits pausing a filing to the window before its due dateBreaking change
Breaking changeFilings

Pausing a filing now follows the same window as the Kintsugi app. After the 15th of the month a filing is due, it can no longer be paused with any pauseIntent, including assistance and skip, which were accepted before. A review pause also needs a pausedUntilDate from today through the 15th of the due month; a date in the past, accepted before, is now refused. A date that is still today anywhere in the world counts as today. POST /filings/{filing_id}/pause answers a refused pause with 400 and code invalid_request, and POST /filings/bulk/pause still answers 200, listing each refused filing in failed.

What to do
  • Pause a filing no later than the 15th of the month it is due.
  • For a review pause, send a pausedUntilDate no earlier than today and no later than the 15th of the due month.
  • After a bulk pause, check failed for filings that were not paused.
Requires a unique name when a portfolio creates an organizationBreaking change
Breaking changeOrganizations

When a portfolio credential creates an organization with POST /organizations, the name must now be unique, ignoring letter case. A name already in use answers 409 with code conflict and the message An organization with this name already exists. Before, the 2026-07-21 release accepted any name, including one already in use or one that differed only in letter case, such as acme beside Acme. Creating an organization from a user session without a portfolio is unchanged.

What to do
  • Handle 409 with code conflict by asking for a different name.
  • Do not retry a refused name with different letter case: it is refused the same way.
Returns already_connected when an activated store is already connectedBreaking change
Breaking changeConnections

When POST /connections/apideck/{conn_id}/activate finds that the shopId belongs to a connection your organization already has, it reactivates that existing connection, removes the one being activated, and answers 400 as before. The error code is now already_connected instead of invalid_request, with the message This store is already connected. The existing connection was reactivated. The store is connected and nothing more is needed. already_connected is a new value of the code field in error responses.

What to do
  • Treat 400 with code already_connected as success, and list your connections again to find the one that remains.
  • Stop relying on invalid_request to detect an already connected store.
  • If your client accepts only known code values, add already_connected.

2026-10-02

Breaking changes
Applies one access rule to every address changeBreaking change
Breaking changeAddresses

The five endpoints that change addresses now accept the same callers: any member of the organization, a portfolio Owner or Admin who manages it, or an API key for the organization. A portfolio Member now receives 403 with code forbidden from POST /addresses/approve, which accepted them before. The other four, which accepted only the organization's Owner among its own users, now also accept its Admins and Members, who received 403 before. An organization you cannot access still answers 404, and API keys work on all five as before.

What to do
  • Have a portfolio Owner or Admin approve addresses, or approve with the organization's API key.
  • Handle 403 with code forbidden from POST /addresses/approve.
  • If your app hid these address actions from organization Admins and Members, you can now offer them.
Requires a non-empty userId for imports started with an API keyBreaking change
Breaking changeImports

On POST /imports/initiate and POST /imports/upload-urls, whether you send userId now depends on your credential. With an API key it is required and must not be blank: a missing userId answers 400 with code invalid_request instead of 422, and an empty or whitespace-only value, accepted before, is now refused the same way. With a signed-in user session, userId is optional and ignored, and the import is recorded under that user.

What to do
  • With an API key, always send a non-empty userId that names the person or process uploading.
  • Expect 400 with code invalid_request, not 422, when userId is missing.

2026-09-22

Breaking changes
Requires a request body to deregister a registrationBreaking change
Breaking changeRegistrations

Deregistering now records when and why the registration closes. POST /v1/registrations/{registration_id}/deregister requires a JSON body with closure_date, reason and final_return_acknowledged, so a request with no body, which succeeded before, is now rejected with 422. The 2026-07-21 release changed the same way, with the fields closureDate, reason and finalReturnAcknowledged.

What to do
  • Send closure_date: the date the registration closes with the jurisdiction, as YYYY-MM-DD. Past and future dates are accepted.
  • Send reason: FULL_BUSINESS_CLOSURE or CLOSING_NEXUS_IN_STATE.
  • Send final_return_acknowledged: true, confirming that a final return is still owed.
Returns the existing credit note when a credit note is created twiceBreaking change
Breaking changeTransactions

Creating a credit note with an external_id already used for a credit note on the same original transaction used to fail with 409 Conflict. It now succeeds and returns the stored credit note unchanged. On v1 that response is 200, and creating a new credit note now answers 201 instead of 200. On the 2026-07-21 release the stored credit note comes back with 202, the same as a new one. The same external_id against a different original transaction still returns 409.

What to do
  • On v1, treat both 201 and 200 as success.
  • Stop relying on 409 to detect an existing credit note.
  • To change an existing credit note, update it: PUT /v1/transactions/{original_transaction_id}/credit_notes/{credit_note_id} on v1, or PATCH /transactions/{transaction_id} on the 2026-07-21 release.

2026-09-21

Breaking changes
Returns the existing record when a physical nexus is created twiceBreaking change
Breaking changeNexus

Creating a physical nexus for an organization, country, state and category that already has one used to fail with 409 Conflict. It now succeeds and returns the stored record unchanged: the dates and address in the request are not applied. On v1 and the Partner API the response is 200, the same as for a new record. On the 2026-07-21 release it is 200 for an existing record and 201 for a new one.

What to do
  • Stop relying on 409 to detect an existing record.
  • To change an existing record's dates or address, update it: PUT /v1/nexus/physical_nexus/{physical_nexus_id} on v1, or PATCH /physical-nexus/{physical_nexus_id} on the 2026-07-21 release.

2026-09-17

Breaking changes
Returns the existing product when a product is created twiceBreaking change
Breaking changeProducts

Creating a product with an external_id and source that already exist used to fail with 409 Conflict. It now succeeds with 200 and returns the stored product unchanged: the fields in the request are not applied. A product you deleted is restored instead, with status PENDING, and is not used in tax calculation until it is approved again. Creating a new product now answers 201 instead of 200.

What to do
  • Treat both 201 and 200 as success.
  • Stop relying on 409 to detect an existing product.
  • To change an existing product, update it with PUT /v1/products/{product_id}.
Kintsugi API Changelog: 2026