KintsugiKintsugi
API Guides

2. Product & Customer Records

Product and customer records are the foundation of every Kintsugi integration. Products carry the tax classification that decides whether an item is taxable in a given jurisdiction. Customer records anchor exemptions to the buyers who hold them. This guide covers when to create each record, how to reference them, and how to verify they landed.

Understanding Product Records

A product record maps one of your catalog items to a Kintsugi tax classification. Each record holds:

  • Your identifier for the item (external_id) plus its name and description
  • A tax classification (product_category and product_subcategory)
  • A tax-exempt flag (tax_exempt)
  • An approval status (status)

Transactions and tax estimates reference products by external_product_id. Kintsugi reads the matching product's classification to decide whether the item is taxable where your customer is.

Create products first: Transactions reference products by external_product_id, so create your catalog before calling /v1/transactions. Tax estimates can classify an item inline by sending product_category and product_subcategory alongside the external_product_id, which creates the product on the fly, but a pre-built catalog keeps classification consistent across every call.

Creating Product Records

Create products with POST /v1/products.

Required Fields

  • external_id: Your unique identifier for the product (for example, "SKU-12345")
  • name: Product name
  • product_category: High-level category, such as Physical, Digital, or Service
  • product_subcategory: Subcategory within that category, such as General Clothing or B2B SaaS
  • tax_exempt: Whether the product is exempt from tax

Optional Fields

  • description: Product description
  • status: Approval status (APPROVED, PARTIALLY_APPROVED, or PENDING). Defaults to APPROVED
  • source: Where the record originated. Defaults to OTHER

Pull the category list from the API: Supported categories and subcategories are returned by GET /v1/products/categories. Read from that endpoint rather than hardcoding values, so your mapping stays valid as the taxonomy grows.

Verifying Product Records

Confirm your catalog with GET /v1/products. The endpoint is paginated (page, and size up to 100) and supports:

  • query for a free-text search across name and other details
  • product_category__in and product_subcategory__in to check classification coverage
  • status__in to surface anything still PENDING
  • source__in and order_by to scope and sort results

To fetch one product directly, use GET /v1/products/{product_id} with the Kintsugi product ID returned at creation.

Store the Kintsugi product ID: GET /v1/products searches by free text, not by exact external_id. Saving the id from your create response gives you a precise lookup later.

Product Creation Workflow

Products carry the tax category that drives every rate lookup. Create them before the first transaction.

Prepare and validate the payload
Five fields are required before you send anything.
external_idnameproduct_categoryproduct_subcategorytax_exempt
Pull the category and subcategory values from GET /v1/products/categories rather than hardcoding them.
Create the product
POST/v1/productsReturns the product id
Non-2xx? See error handling below.
Verify it exists
GET/v1/productsOptional, recommended
Product is ready for tax calculations
Reference it by external_id in estimates and transactions.

Understanding Customer Records

A customer record identifies a buyer and gives exemptions something to attach to. Create customer records when you sell to:

  • Nonprofit organizations
  • Government agencies
  • Resellers holding valid exemption certificates
  • Any other exempt entity

Exemptions themselves are separate records created against a customer through the exemptions API. Once an exemption is on file, Kintsugi applies it when that customer appears on a tax estimate or transaction.

When you don't need customer records: Selling only to ordinary consumers? Skip customer creation and pass the buyer's details inline on the transaction's customer object.

Creating Customer Records

Create customers with POST /v1/customers. The API accepts a partial record, so send everything you have; in practice, exemption matching and address-based tax work depend on the fields below.

Fields to Send

  • external_id: Your unique identifier for the customer (for example, "CUST-789")
  • name: Customer or business name
  • email: Customer email address
  • Address fields: street_1, street_2, city, county, state, postal_code, and country (ISO 3166-1 alpha-2), or a single full_address string in their place

Other Optional Fields

  • phone: Contact number
  • status: ACTIVE or INACTIVE. Defaults to ACTIVE
  • registration_number: The customer's registration number
  • customer_tax_registrations: The customer's tax registrations, where you track them

Customer Addresses

A customer record carries one address, written as flat fields on the record itself rather than as a list. That address identifies the customer; it does not decide the tax jurisdiction on its own.

Jurisdiction comes from the addresses on the transaction or estimate, where each entry has a type of SHIP_TO, BILL_TO, SHIP_FROM, or BILL_FROM. The SHIP_TO address determines which rates apply, and Kintsugi falls back to BILL_TO when no SHIP_TO address is present.

Adding Exemptions

With the customer created, attach the exemption using POST /v1/exemptions. That request needs:

  • exemption_type: The kind of exemption, such as wholesale or resale
  • start_date: When the exemption takes effect (YYYY-MM-DD)
  • customer_id: The Kintsugi customer ID from your create response
  • FEIN: Federal Employer Identification Number
  • sales_tax_id: Sales tax ID on the certificate
  • status: Exemption status, for example ACTIVE

Add jurisdiction, country_code, end_date, and reseller where they apply, and upload the certificate itself with POST /v1/exemptions/{exemption_id}/attachments.

Verifying Customer Records

Confirm your customers with GET /v1/customers. The endpoint is paginated (page, and size up to 100) and supports:

  • search_query for a free-text search across name and other details
  • country and state to scope results by geography
  • source__in and order_by to filter and sort

For an exact lookup, use GET /v1/customers/external/{external_id} with your own identifier, or GET /v1/customers/{customer_id} with the Kintsugi customer ID.

Customer Creation Workflow

A customer record is only required when exemptions are involved. Everyone else can be passed inline.

QDoes this customer hold an exemption?
NOSkip the customer record
Pass customer data inline on the transaction
The address on the transaction is enough to source the sale. Nothing else to create.
YESCreate the record so exemptions can attach to it
Prepare and validate the payload
The API accepts a partial record, so send everything you have. These are what exemption matching and address-based rates depend on.
external_idnameemail
Plus the address: street_1, city, state, postal_code and country, or a single full_address in their place. Run it through address validation first, since a bad address means a wrong rate.
Create the customer
POST/v1/customersReturns the customer id
Non-2xx? See error handling below.
Attach the exemption
One per jurisdiction the customer is exempt in. Without an exemption on file, tax is still charged.
POST/v1/exemptionsNeeds the customer id
Then upload the certificate itself to POST /v1/exemptions/{exemption_id}/attachments.
Verify it exists
GET/v1/customersOptional, recommended
Customer is ready for transactions
Exemptions apply automatically on every matching sale.

Using Products and Customers in Transactions

With records in place, reference them from your tax estimates and transactions.

Referencing Products

Each line item points at a product through external_product_id:

{
  "transaction_items": [
    {
      "external_id": "ITEM-001",
      "date": "2026-01-15T10:00:00Z",
      "external_product_id": "PROD-12345",
      "quantity": 2,
      "amount": 100.00
    }
  ]
}

Kintsugi resolves the product and applies its classification to calculate tax.

Referencing Customers

Transactions and estimates carry the buyer on a customer object. Send your external_id there to match an existing record:

{
  "customer": {
    "external_id": "CUST-789",
    "name": "Northwind Nonprofit",
    "email": "ap@example.org"
  },
  "transaction_items": [],
  "addresses": []
}

When the external_id matches a customer on file, Kintsugi applies that customer's exemptions. If no record matches, the details you send are used for the transaction and the exemption lookup finds nothing to apply. You can also reference a customer on a transaction by their Kintsugi ID using customer_id.

Updating Product and Customer Records

Update with PUT /v1/products/{product_id} and PUT /v1/customers/{customer_id}. Typical cases:

  • Products: Reclassifying category or subcategory, changing the tax_exempt flag, revising name or description
  • Customers: Correcting an address, updating contact details, changing status

Product updates are full replacements: PUT /v1/products/{product_id} requires name, product_category, product_subcategory, and tax_exempt on every call. Send the complete record, not just the fields you are changing.

Updates do not rewrite history. Only future tax calculations and transactions use the new values.

When to update versus create new: If an item's tax treatment fundamentally changes, for example moving from physical goods to a digital download, create a new product under a new external_id instead of editing the old one. That keeps a clean audit trail of when the classification changed.

Best Practices

Product Management

  • Build the catalog first: Have products in place before you wire up tax calculation or transaction sync
  • Read categories from the API: Source values from GET /v1/products/categories instead of hardcoding them
  • Use consistent external IDs: Pick one convention, such as always the SKU, and hold it across every system
  • Batch creation: Send products in chunks to stay within rate limits
  • Verify before you rely on them: Confirm products exist before referencing them in transactions

Customer Management

  • Create records where exemptions live: Ordinary consumers can travel inline on the transaction
  • Validate addresses: Run addresses through the address validation API before you save them
  • Store Kintsugi customer IDs: You need the id to attach exemptions and for exact lookups
  • Handle exemptions as a second step: Create the customer, then attach exemptions through the exemptions API

Error Handling

Same policy for products and customers. Read the response, then decide whether the failure is worth retrying.

RETRYABLE5xx · 429
Back off, then re-send
Wait with exponential backoff, then send the identical payload. A 5xx can still leave the record written, so look it up before re-sending: external_id has to stay unique, and a blind retry can come back as a duplicate instead.
NOT RETRYABLE4xx
Fix the data, then re-send
The response body names the offending field. Correct it, re-validate, and start again from step 1. Retrying unchanged will fail the same way.
Cap retries. Three attempts is plenty. After that, log the payload and the response and surface it for a human rather than looping.

Common Failures

What actually goes wrong when creating products and customers:

  • Duplicate external_id: Look the record up before creating it
  • Invalid category or subcategory: Match values to GET /v1/products/categories
  • Missing required fields: Products need external_id, name, product_category, product_subcategory, and tax_exempt
  • Invalid address: Validate addresses before saving them
  • Missing authentication headers: Every request needs both x-api-key and x-organization-id

For the full status-code reference and retry code samples, see the Error Handling guide.

Integration Checklist

Before you wire up tax calculation or transaction sync:

  • Created product records for every item in your catalog
  • Verified products exist and carry the classification you expect
  • Created customer records for exempt entities (if applicable)
  • Attached exemptions to those customers and uploaded certificates (if applicable)
  • Tested product lookup in a sample tax estimate request
  • Tested customer lookup in a sample transaction request

Next Steps

With products and customers in place:

  1. Start calculating tax: Reference products in /v1/tax/estimate requests. See the Sales Tax Calculations guide.

  2. Sync transactions: Reference products and customers in /v1/transactions requests. See the Syncing Transaction Records guide.

  3. Handle updates: Set up workflows to push catalog and customer changes through to Kintsugi.

For endpoint-level detail, see: