# 3. Syncing Transaction Records (2026-07-21)

> Sync completed sales transactions to Kintsugi for compliance tracking and nexus determination

Source: https://docs.trykintsugi.com/docs/2026-07-21/api-guides/syncing-transaction-records

Transaction sync (also called Level 1 or L1) creates the permanent record of your completed sales in Kintsugi. Those records drive nexus tracking, compliance reporting, and filing preparation. Every Kintsugi integration rests on them, whether you run L1 only, tax calculation only, or L2. This guide covers when to sync, how to shape the payload, and how to run a clean bulk import.

## Understanding Transaction Sync

Each transaction represents one completed sale, carrying:

Transaction details: date, type, amount, currency

Line items that reference your products

Customer details and addresses

Tax amounts you already collected, when tax was charged at checkout

Kintsugi uses those records to:

Determine economic nexus by tracking sales volume and transaction counts by jurisdiction

Prepare filings by aggregating transactions per jurisdiction

Maintain an audit trail for compliance

Track refunds and credit notes against original sales

Transaction sync (L1) is the foundation: POST /transactions records sales; tax on them is calculated asynchronously afterwards. With the tax engine (L2) enabled, Kintsugi prices tax at checkout through POST /tax-estimations and you still sync the completed transaction afterward. Tax calculation without transaction sync is only viable when nexus and compliance are managed elsewhere. See Planning an Integration.

## When to Sync Transactions

Sync once the sale is complete and payment is confirmed. The cadence is yours to choose.

Real-Time Sync

Sync immediately after order completion when you have:

High-volume e-commerce

A requirement for immediate compliance visibility

Real-time reporting needs

Real-time sync keeps your nexus status and compliance data current to the minute.

Batch Sync

Sync in batches when you have:

An accounting system integration

Periodic order exports

A daily or weekly operational rhythm

Batching suits systems that already process orders in groups.

Batch cadence: Sync at least daily. Economic nexus thresholds are evaluated over a rolling 12-month period or a calendar year depending on the state, so a daily rhythm keeps your tracking gap-free.

## Transaction Statuses

Status decides whether a transaction affects your compliance position. A transaction's status reads back as one of PENDING, COMMITTED, CANCELLED, FULLY_REFUNDED, PARTIALLY_REFUNDED, or INVALID.

COMMITTED

Counts toward filed liability. A sale you record through POST /transactions is stored with this status.

PENDING

May still change, and does not count toward filed liability.

The create and update requests have no status field, so the Tenanted API does not let you record a sale as pending or move it between statuses yourself.

Refunds are tracked separately: A sale that has been credited keeps its own status, and its refund position is held apart from it. To find refunded sales, filter GET /transactions with refundStatus=FULLY_REFUNDED,PARTIALLY_REFUNDED. See Handling Refund Transactions for how credit notes drive it.

## Choosing a Sync Pattern

Because a sale recorded through the API is stored as COMMITTED and counts at once, sync it after payment clears. The payment gate comes first: nothing is sent until you know the order is real.

1

Order placed, payment processes

Entirely in your system. No Kintsugi call yet.

DECLINED → Stop. Don't sync. There is no transaction in Kintsugi, so there is nothing to reverse.

2

Assemble and check the payload

externalId date currency addresses items customer

Every product should already exist as a product record, and every address should validate.

3

Send the transaction

POST /transactions type: SALE

Answers 202 Accepted with the recorded transaction.

4

Synced and counting toward nexus

Tax is calculated asynchronously. Read the transaction back and watch processingStatus: PROCESSED means tax calculation has completed.

GET /transactions/{transaction_id} answers 404 until processing completes, so poll it rather than treating the first 404 as a failure.

No create-pending-then-commit pattern: The v1 API lets you record a sale as PENDING and commit or cancel it later. The Tenanted API has no status on create or update, so that pattern is not available here. Hold the sale in your own system until the payment outcome is known.

## Creating Transactions

Create transactions with POST /transactions, one transaction per request.

POST /transactions

-H "Api-Key: ***"

-H "Api-Version: 2026-07-21"

{

"externalId": "order-2001",

"date": "2026-01-15T14:30:00Z",

"type": "SALE",

"currency": "USD",

"totalAmount": "100.00",

"source": "API",

"description": "Order 2001",

"addresses": [

{

"type": "SHIP_TO",

"street1": "123 Main St",

"city": "San Francisco",

"state": "CA",

"postalCode": "94107",

"country": "US"

}

],

"items": [

{

"externalProductId": "SKU-ABC",

"date": "2026-01-15T14:30:00Z",

"product": "Widget",

"quantity": "2",

"amount": "100.00"

}

]

}

Required Fields

externalId: Your stable identifier for the transaction (for example, "order-2001")

date: When the transaction occurred, as an RFC 3339 timestamp. It drives which filing period the sale lands in, so send the real transaction time, not the time of the call

currency: ISO 4217 currency code of every amount, for example USD

Recommended Fields

type: Transaction type. SALE records a sale and is the default

totalAmount: Defaults to "0.00", so send the real total

addresses: Jurisdiction is resolved from these, so an incomplete address means tax cannot be calculated accurately

items: The line items sold

customer: The buyer, with externalId, name, email, and companyName. Omit it for a sale with no customer identity, such as a marketplace or point-of-sale sale

source: Where the sale originated, for example API. Defaults to OTHER

description: A human-readable label that pays for itself when reconciling

## Creating Transactions

marketplace: true for reseller or marketplace orders where tax was remitted by someone else. Tax liability is excluded. Whether gross sales count toward a state's nexus threshold depends on the state, as each nexus period's includeMarketplaceTransactions shows

Your organization comes from the credential: The request body carries no organization field. When your key can reach more than one organization, choose one with an Organization-Id, Connection-Id, or Entity-Id header, and let the body describe the sale.

Money fields are decimal strings, such as "100.00". Re-sending an externalId that already exists does not create a second transaction.

Transaction Items

Each line item points at a product:

externalProductId (required): The product's identifier in your system

date (required): Date and time of the line, normally matching the transaction date

externalId: Your identifier for the line item. Send it on every line: a credit note can only reverse a line by its externalId

quantity: Defaults to "1"

amount: Line amount before tax. Defaults to "0.00", so send the real figure

product and description: Product name and line description

taxAmountImported: Tax you already collected on this line, if any

Addresses

Every address entry needs a type of SHIP_TO, BILL_TO, SHIP_FROM, or BILL_FROM, plus the address itself: street1, street2, city, county, state, postalCode, and country (ISO 3166-1 alpha-2).

Tax jurisdiction usually follows the SHIP_TO address, or BILL_TO when there is no ship-to.

## Creating Transactions

Transactions are processed asynchronously: POST /transactions returns 202 Accepted with the recorded transaction, a processingStatus of QUEUED, and tax totals of "0.00". totalTaxAmountCalculated and the per-line taxItems populate shortly afterwards. The returned id is not fetchable straight away either: GET /transactions/{transaction_id} answers 404 until processing completes, so poll it rather than treating the first 404 as a failure.

## Historical Transaction Sync

Transaction sync integrations start with a historical import covering the previous full calendar year through today. This one-time operation sets your nexus tracking baseline.

Historical Data Requirements

Cover:

Start date: January 1st of the previous calendar year

End date: Today, or your integration start date

Scope: All completed sales in that window

What if I don't have complete historical data?

Send what you have. Kintsugi tracks nexus forward from the data it receives. You may need to set registration effective dates manually where records are missing. Contact support and we will work through it with you.

Should I sync refunded transactions?

Yes. Sync the sale, then record each refund as a credit note against it. The result is a complete, defensible audit trail. See Handling Refund Transactions.

How do I handle large historical imports?

Chunk by date range and send transactions in groups, pausing between chunks. Because processing is asynchronous, you can move large volumes without long-running requests. If you would rather not build an importer, CSV file upload covers the same ground.

Bulk Import Strategy

For large historical imports:

Chunk by date range: Work month by month or week by week

Batch your requests: The endpoint takes one transaction per call, so send them in groups and pause between groups

Handle errors deliberately: Log failures with their requestId, fix the data, replay the batch

Verify completion: Reconcile with GET /transactions by date range against your source-of-truth counts

Order matters: Import oldest first. Nexus is evaluated against transaction dates, and a chronological import keeps threshold crossings accurate as they are calculated.

## Verifying Transactions

Read transactions back with GET /transactions. The endpoint is cursor-paginated ( limit up to 100, default 50, plus cursor) and supports:

startDate and endDate ( YYYY-MM-DD) for date ranges

status and processingStatus (comma-separated) to separate committed, pending, and still-processing records

search for a free-text search over transaction id, externalId, externalFriendlyId, description, and customer name

type, country, state, marketplace, exempt, source, and filingId to narrow further

sort and order to sort. The default is date, descending, so newest first

For a direct lookup, use GET /transactions/{transaction_id} with the Kintsugi transaction ID. The Tenanted API has no lookup by externalId; use search instead.

## Updating Transactions

Update with PUT /transactions/{transaction_id}. It is a replace: send externalId, date, and currency on every call, and the scalar fields and the customer are overwritten with what you send. Typical cases:

Address corrections: Addresses are replaced per type, so a SHIP_TO you send replaces the stored ship-to and a type you omit is left as it was

Amount adjustments: Correcting totals or line items. Lines are matched by externalId: a new externalId is added, and a stored line whose externalId you do not send is removed

The transaction's type cannot be changed, and tax is recalculated asynchronously after the update. Credit notes have their own update, PATCH /transactions/{transaction_id}.

Filed transactions lock: A locked or already-filed transaction answers 409 and can no longer be updated. Make corrections before the filing period closes.

To remove a sale entirely, Archive a transaction. Archiving is one-way: the transaction disappears from every read, cannot be restored, and stops counting toward nexus. A locked or already-filed transaction cannot be archived.

## Best Practices

Data Quality

Use consistent external IDs: One convention across every system, on the transaction and on every line

Validate before syncing: Confirm products exist and addresses are valid first

Send complete data: Fields with defaults, especially totalAmount and item amount, will silently post as zero if you omit them

Get timestamps right: Send the real transaction time on date, as an RFC 3339 timestamp

Sync Timing

Sync after payment confirmation: A synced sale is committed and counts at once

Sync in chronological order: Oldest first, especially on historical imports

Store Kintsugi transaction IDs: You need the id for updates, credit notes, and direct lookups

Monitor the pipeline: Track both request success and processingStatus on the records you create

Error Handling

Common failures when syncing transactions:

Invalid address: Validate addresses before syncing

Missing required fields: externalId, date, and currency are required. The error's errors array names each field that failed

Locked transaction: Updating or archiving a filed transaction returns 409

Missing or invalid API key: Every request needs a valid Api-Key header, or it returns 401

See the Error Handling guide for detailed strategies.

## Integration Patterns

E-Commerce Platforms

E-commerce platforms typically sync the moment an order completes:

Order is placed and payment confirmed

Create the transaction with type: "SALE"

Include every line item with its product reference and line externalId

Include the shipping address so the jurisdiction resolves correctly

Subscription Platforms

Subscription platforms sync per billing cycle:

The subscription invoice is generated

Create the transaction once the invoice is paid

Reference the subscription product and the customer

Include the billing address

Accounting Systems

Accounting systems sync in batches:

Export completed invoices and sales

Create transactions with type: "SALE"

Process in date order, oldest first

Retry failures after correcting the underlying data

## Next Steps

With transaction sync running:

Handle refunds: Record credit notes against original sales. See the Handling Refund Transactions guide.

Query transactions: Use the GET endpoints for reporting and reconciliation. See the List transactions API reference.

Monitor sync health: Watch request success rates and processingStatus so failures surface early.

For endpoint-level detail, see:

Create a transaction

List transactions

Get a transaction by id

Update a transaction

---

Index of every page: https://docs.trykintsugi.com/llms.txt
