API changelog
Every change to the Kintsugi API and every release, newest first. Breaking changes carry the mark. Tenanted releases are dated, and you choose one with the Api-Version header.
Changes
2026-09-22
Requires a request body to deregister a registrationRegistrations
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.
- 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_CLOSUREorCLOSING_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 twiceTransactions
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.
- On v1, treat both
201and200as success. - Stop relying on
409to 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, orPATCH /transactions/{transaction_id}on the 2026-07-21 release.
2026-09-21
Returns the existing record when a physical nexus is created twiceNexus
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.
- Stop relying on
409to 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, orPATCH /physical-nexus/{physical_nexus_id}on the 2026-07-21 release.
2026-09-17
Returns the existing product when a product is created twiceProducts
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.
- Treat both
201and200as success. - Stop relying on
409to detect an existing product. - To change an existing product, update it with
PUT /v1/products/{product_id}.
Releases
2026-07-21
LatestTenanted APIIntroducing the Tenanted API
A fresh foundation for building on Kintsugi. The Tenanted API is versioned by date, and you choose the release you build against. It speaks one consistent dialect from end to end: clean paths, camelCase fields, exact decimal amounts, and a single error format. And it is built for scale, with one credential reaching every organization it owns.
Compared with v1
| Topic | v1 | 2026-07-21 |
|---|---|---|
| Versioning | The /v1 path prefix | The Api-Version header, dated YYYY-MM-DD. Optional; without it, a request runs against the launch release |
| Paths | /v1/transactions | /transactions |
| Authentication | x-api-key | Api-Key. Endpoints that manage people accept a signed-in session token instead |
| Choosing an organization | x-organization-id, required on almost every request | One credential reaches every organization it owns. Narrow a request with Organization-Id, Connection-Id, or Entity-Id |
| Field names | snake_case | camelCase |
| Money and rates | Decimal strings out, numbers or strings in | Decimal strings at a fixed scale: amounts to 2 places, rates to 9 |
| Timestamps | No single documented format | RFC 3339 in UTC, always ending in Z |
| Errors | Shapes vary by endpoint | One envelope everywhere: code, message, requestId, and errors |
| Portfolio | Not available | Portfolio and Portfolio Reseller endpoints, for partner accounts |
Moving an integration from v1
- Send
Api-Version: 2026-07-21with every request, so your integration stays on this release until you decide to move. - Drop
/v1from your paths. - Send your key as
Api-Key, and replacex-organization-idwithOrganization-Idwherever you target one organization. - Rename fields to camelCase, and read every amount as a decimal string, never a float.
- Branch on the error
code, not the message or the HTTP status, and quoterequestIdwhen you contact support.
Creating a transaction answers 202 Accepted straight away, and tax is calculated just after. Check processingStatus before you read the tax totals.
v1
LegacyThe original Kintsugi API, versioned in the path. It remains the default in these docs and is documented exactly as before, so existing integrations can keep running with confidence. New integrations should start on the Tenanted API.