TrueSpec

Integrate the TrueSpec catalog API

One bearer key reads every catalog your organization has been granted, merged into a single normalized feed. Clean JSON, cursor pagination, conditional requests, and incremental sync so your nightly job pulls only what changed. This page is the practical walkthrough; the full reference is the interactive OpenAPI docs (ReDoc if you prefer).

1. Get a key

An owner in your organization creates API keys under Keys once a publisher has granted you access (or after your access request is approved). The raw token — dxk_… — is shown once at creation. Store it in your secret store; it can be rotated or revoked at any time without touching the grant.

2. First call

curl -s https://truespec.net/v1/products \
  -H "Authorization: Bearer dxk_YOUR_KEY"

Every list response is the same envelope — items plus an opaque cursor:

{
  "items": [
    {
      "id": "prod_01ksessas63k7c5e375aqbgj8r",
      "sku": "TT-HRV-1X6-SQR-BS",
      "brand": "TimberTech",
      "name": "1x6 Square-Shouldered Harvest Decking - Brownstone",
      "attributes": { "color": "Brownstone", "material": "composite" },
      "primary_image_url": "https://images.truespec.net/i/.../medium.webp",
      "variant_count": 3,
      "variants_url": "/v1/products/prod_01ksessas.../variants",
      "updated_at": "2026-06-04T18:22:31Z"
    }
  ],
  "next_cursor": "eyJ1IjoiMjAyNi0wNi0wNFQxOD..."
}

Pages are 50 items by default, up to 200 with ?limit=200. Pass next_cursor back as ?cursor=… for the next page; null means you have everything. Cursors are opaque — don't parse them. GET /v1/products/{id} returns the full detail (inline variants, typed documents[] — spec sheets, warranties, SDS), and GET /v1/categories returns the category tree with each category's attribute_schema, so your importer knows which attribute keys to expect per category.

3. Sync deltas, not full catalogs

Every list endpoint takes updated_since (ISO 8601; strictly-greater-than) and orders results oldest-change-first. So the checkpoint for your next run is simply the updated_at of the last item you processed:

# nightly_sync.py — pull only what changed since the last run
import requests

BASE = "https://truespec.net/v1"
HEADERS = {"Authorization": "Bearer dxk_YOUR_KEY"}

def sync(checkpoint: str | None) -> str | None:
    params = {"limit": 200}
    if checkpoint:
        params["updated_since"] = checkpoint
    while True:
        r = requests.get(f"{BASE}/products", headers=HEADERS, params=params)
        r.raise_for_status()
        page = r.json()
        for product in page["items"]:
            upsert_into_your_system(product)   # keyed on product["id"]
            checkpoint = product["updated_at"]
        if page["next_cursor"] is None:
            return checkpoint                  # save for the next run
        params["cursor"] = page["next_cursor"]

Responses also carry ETag and Last-Modified; send If-None-Match back and an unchanged page costs you a 304 with no body. From PowerShell-land, the first call is one line:

Invoke-RestMethod -Uri "https://truespec.net/v1/products" `
  -Headers @{ Authorization = "Bearer dxk_YOUR_KEY" }

4. Resolve your own item numbers

After your organization uploads its item list at Enrichment, your storefront or ERP can look up vendor product data under your own SKUs:

curl -s https://truespec.net/v1/products/by-consumer-sku/YOUR-ITEM-123 \
  -H "Authorization: Bearer dxk_YOUR_KEY" -i

The body is the standard product detail; how the match was made rides in headers: X-TrueSpec-Match-Basis (gtin / vendor_sku / manual), X-TrueSpec-Match-Confidence, and X-TrueSpec-Matched-Variant. Ad-hoc lookups work too: ?vendor_sku=LCGV5412E and ?gtin=… on the list endpoint, alongside ?brand= and ?category= filters (brand matching is case- and punctuation-insensitive).

5. Operational facts

ThingBehavior
Rate limitPer key (default 600 req/min). Watch X-RateLimit-Limit / -Remaining / -Reset; a 429 carries Retry-After.
ErrorsAlways {"error": {"code", "message", "request_id"}} with a closed, documented code enum (e.g. invalid_cursor, rate_limited). Quote request_id (also the X-Request-Id header) in support requests.
IDsprod_… / var_… public ids are permanent — safe foreign keys in your system.
ContractChanges within /v1/ are additive only — new fields appear, existing ones never break. Breaking changes would ship as /v2/.
Open the API reference → Ask us anything

Integrating an ERP or eCommerce platform and want a sounding board? Talk to us — we've wired this into the systems this industry actually runs.