Tesseract-Tax Cloud™
Partner API reference
← Console

Getting started

All endpoints live under https://platform.knottheory.ai/partner/v1. Authenticate every request with your key in the X-API-Key header. Keys carry scopes (endpoint families you can call) and monthly quotas (metered calls per family, UTC calendar month). Request bodies are JSON unless noted; unknown fields are rejected — a typo silently defaulting to zero would be a wrong tax number, so we refuse instead.

curl https://platform.knottheory.ai/partner/v1/usage -H "X-API-Key: $TTC_KEY"

Need a key? Email sales@knottheory.ai. Keys are shown once at mint and stored only as a hash.

Identity & usage

Introspect your own key — also the console's sign-in check.

GET/usagefree

Key name, scopes, and this month's metered usage vs quota per endpoint family.

Response
{
  "name": "Full Demo (all scopes)",
  "scopes": ["estimate", "documents", "salestax"],
  "usage": {
    "estimate":  {"used": 0, "quota": 500},
    "salestax":  {"used": 6, "quota": 500},
    "documents": {"used": 0, "quota": 100}
  },
  "created_at": "2026-08-07T18:07:44+00:00"
}

Sales tax — quotes

Rates from official state sources only (SST rate & boundary files, state DOR feeds), refreshed daily. Every quote names its source and precision; component taxes always sum exactly to the quoted tax.

POST/sales-tax/quotescope: salestaxmetered

Quote tax for a sale by destination. ZIP gives the highest precision in the 24 SST member states; CA resolves by city; every state has a reviewed base rate.

  • • precision tiers: zip-official (≥90% boundary agreement) · zip-majority (ZIP spans jurisdictions; share disclosed) · zip-incomplete (a jurisdiction at the ZIP has no current rate; the note names it) · city-official · state-base · no-sales-tax
  • • Optional taxability_ref: an SSUTA reference number (see /sales-tax/taxability). Items the destination state's matrix marks exempt quote at zero with the statute cited; other treatments are confirmed in the notes. Also accepted on POST /sales-tax/transactions.
  • • components[] carries the per-jurisdiction split — state / county / city / district, each with its own rate, penny-allocated so the parts sum exactly to tax.
Request
{"state": "KS", "zip": "67217", "amount": 250}
Response
{
  "state": "KS", "jurisdiction": "KS 67217",
  "rate": 0.075, "tax": 18.75, "total": 268.75,
  "precision": "zip-official",
  "source": "SST rate & boundary files (official)",
  "notes": ["Composite of state 6.500% + county 1.000% + city 0.000% for ZIP 67217."],
  "components": [
    {"level": "state",  "juris_type": "45", "juris_code": "20",    "rate": 0.065, "tax": 16.25},
    {"level": "county", "juris_type": "00", "juris_code": "173",   "rate": 0.01,  "tax": 2.50},
    {"level": "city",   "juris_type": "01", "juris_code": "79000", "rate": 0.0,   "tax": 0.00}
  ]
}
GET/sales-tax/taxabilityscope: salestaxmetered

Search a member state's published SST Taxability Matrix by item text (?q=clothing) or SSUTA reference number (?ref=20010). Answers carry the state's own treatment, statute cite, and matrix version — never our interpretation. Refreshed daily; new published versions are picked up automatically.

Request
?state=MN&q=clothing
Response
[
  {
    "ref_number": "20010", "item": "Clothing",
    "section": "Clothing and related products...",
    "treatment": "exempt",
    "statute": "297A.67 Subd. 8",
    "matrix_version": "2026.0"
  }
]
GET/sales-tax/coveragescope: salestaxfree

What the engine can answer, honestly: per-state jurisdiction counts, ZIP coverage, feed freshness, and the no-sales-tax states.

Sales tax — transaction ledger

Report each sale once; we persist its per-jurisdiction split. Period summaries and reconciliation fall out of aggregation — the same rows an SST Simplified Electronic Return is built from.

POST/sales-tax/transactionsscope: salestaxmetered

Record a sale or refund with its jurisdiction split.

  • • Idempotent on external_id (your invoice/order id): a replay returns the stored transaction with HTTP 200 and is not billed again. Concurrent duplicates get 409 — re-read and retry.
  • • kind: "sale" | "refund" — refunds store negated amounts and net out of summaries.
  • • collected_tax (what you charged the buyer) is stored next to our computed tax; the variance shows in every summary.
  • • Optional merchant: your merchant reference — attaches the sale to that merchant's monthly filing engagement for the destination state, creating it automatically.
Request
{
  "external_id": "ACME-INV-1", "merchant": "acme-001",
  "state": "KS", "zip": "67217",
  "amount": 1000, "collected_tax": 75, "date": "2026-08-06"
}
Response
{
  "id": "018bd417-...", "external_id": "ACME-INV-1", "kind": "sale",
  "date": "2026-08-06", "state": "KS", "jurisdiction": "KS 67217",
  "precision": "zip-official", "amount": 1000.0, "rate": 0.075,
  "tax": 75.0, "collected_tax": 75.0,
  "components": [
    {"level": "state",  "juris_code": "20",  "rate": 0.065, "tax": 65.00},
    {"level": "county", "juris_code": "173", "rate": 0.01,  "tax": 10.00},
    {"level": "city",   "juris_code": "79000", "rate": 0.0, "tax": 0.00}
  ]
}
GET/sales-tax/transactionsscope: salestaxfree

List your transactions (newest first). Filters: state, date_from, date_to, status (confirmed | pending), limit (max 500).

POST/sales-tax/transactions/{id}/confirmscope: salestaxfree

Confirm a pending transaction (one extracted from an uploaded invoice). Only confirmed transactions count toward filing summaries — agents extract, humans certify.

DELETE/sales-tax/transactions/{id}scope: salestaxfree

Void a PENDING extraction (mis-read or duplicate invoice). Confirmed transactions are immutable ledger history — 409.

GET/sales-tax/transactions/{id}scope: salestaxfree

One transaction with its component split. Key-scoped — you can only ever read your own.

GET/sales-tax/transactions/{id}/certificatescope: salestaxfree

Verified-calculation certificate: the Lean 4 proof manifest for the calculation engine (theorems machine-checked for ALL inputs — component taxes sum exactly to the quoted tax, SER tie-outs hold by construction), this transaction's numbers re-verified against those invariants, data provenance, and an audit-risk rating (low/medium/high) with every reason stated. Evidence you can hand an auditor.

GET/sales-tax/summaryscope: salestaxfree

The filing/reconciliation view for one state and period: totals, computed-vs-collected variance, and tax per jurisdiction — the local allocation schedule a state return wants.

Request
?state=KS&date_from=2026-08-01&date_to=2026-08-31
Response
{
  "state": "KS", "period": {"from": "2026-08-01", "to": "2026-08-31"},
  "transactions": 2, "gross_amount": 1250.0,
  "computed_tax": 93.75, "collected_tax": 93.75, "variance": 0.0,
  "jurisdictions": [
    {"level": "state",  "juris_code": "20",    "tax": 81.25, "transactions": 2},
    {"level": "county", "juris_code": "173",   "tax": 12.50, "transactions": 2},
    {"level": "city",   "juris_code": "79000", "tax": 0.00,  "transactions": 2}
  ]
}

Sales tax — merchants & filing engagements

The merchant is the filing identity (TIN encrypted at rest — only the last 4 digits ever appear in a response). Engagements group a merchant's transactions per state per calendar month, automatically, and close into filing periods.

POST/sales-tax/merchantsscope: salestaxfree

Register a seller you file for. Idempotent on external_id — replays return the stored merchant (200) unchanged.

Request
{
  "external_id": "acme-001", "legal_name": "Acme Widgets LLC",
  "tin": "12-3456789", "tin_type": "FEIN",
  "sstp_id": "S00099999", "state_licenses": {"KS": "KS-991122"}
}
Response
{
  "id": "45395ce6-...", "external_id": "acme-001",
  "legal_name": "Acme Widgets LLC",
  "tin_last4": "6789", "tin_type": "FEIN",
  "sstp_id": "S00099999", "state_licenses": {"KS": "KS-991122"},
  "created_at": "2026-08-08T00:32:51+00:00"
}
GET/sales-tax/merchantsscope: salestaxfree

List your merchants.

PUT/sales-tax/merchants/{external_id}/bankscope: salestaxfree

Vault the merchant's ACH-debit details for filing remittance (states pull payment directly from the merchant's account — funds never route through us). Routing numbers are ABA-checksum validated; details are stored envelope-encrypted and decrypted only at return transmission. Responses only ever carry the routing number and account last-4. Re-PUT to replace.

Request
{
  "account_type": "Checking",
  "routing_number": "021000021",
  "account_number": "000123456789"
}
GET/sales-tax/engagementsscope: salestaxfree

List filing engagements. Filters: merchant_id, state, status (open | closed).

GET/sales-tax/engagements/{id}scope: salestaxfree

Engagement detail including its scoped filing summary — the per-merchant return input.

POST/sales-tax/engagements/{id}/closescope: salestaxfree

Close the period. Closed periods refuse new transactions (422) — late arrivals belong on an amended return, never silently mixed into a filed period.

Federal estimates

The same calculation engine that backs our certified IRS e-file path, with every modeling assumption disclosed.

POST/estimatescope: estimatemetered

Federal tax estimate from an income breakdown (wages, self-employment, capital gains, rentals, credits, and more). Unknown fields are rejected, never silently zeroed.

Request
{
  "tax_year": 2026, "filing_status": "single", "states": ["CA"],
  "income": {"wages": 120000, "interest_income": 500}
}
Response
{
  "tax_year": 2026, "filing_status": "single",
  "estimate": { "...": "full line-item breakdown" },
  "assumptions": ["...every modeling position disclosed..."]
}

Document extraction

The classify → parse → verify pipeline behind our portal, as an async API.

POST/documentsscope: documentsmetered

Upload one document (multipart file, 40MB max). Returns 202 with a job id; extraction runs asynchronously.

  • • Invoices → ledger: add form fields purpose=sales and merchant=<your merchant ref> (requires the salestax scope). The file is parsed as a sales invoice and a PENDING transaction is proposed on the merchant's monthly engagement — review it, then confirm or void. If the invoice is missing a ship-to state or amount, the reason appears on the document's error field instead.
GET/documents/{id}scope: documentsfree

Poll a job: queued | processing | done | failed — done carries the document type and typed fields. Every job also reports source (how the document entered the system; api for partner uploads).

Errors

401Missing or invalid X-API-Key.
402Monthly quota for that endpoint family is exhausted — contact sales@knottheory.ai to raise it. Failed requests are never billed.
403Your key lacks the required scope.
404Resource not found, or not yours — lookups are always key-scoped.
409Concurrent duplicate (e.g. two submits of one external_id) — re-read, then retry.
422Validation refused: unknown fields, bad state codes, closed periods, unknown merchants. The detail string says exactly what and why.