Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.closient.com/llms.txt

Use this file to discover all available pages before exploring further.

Closient is API-first and per-app. Each Django app owns its own NinjaAPI instance, mounted at /{app}/api/v1/, with its own OpenAPI 3.1 document at /{app}/api/v1/openapi.json. This skill is the map that gets an agent from “which app owns this concept?” to “this is the endpoint I want to hit” without grepping templates.

When to use

  • An agent knows what data it needs but not which Closient app owns that data.
  • A developer is writing an SDK or MCP server and needs to enumerate every API surface.
  • The agent hit a 404 Not Found and wants to confirm the endpoint path before assuming the API is broken.
For zero-to-first-call setup (auth, scopes, PKCE), run closient-api-quickstart first.

Discover everything from the API catalog

The canonical enumeration is the RFC 9727 linkset at /.well-known/api-catalog:
GET /.well-known/api-catalog
Accept: application/linkset+json
Each entry has:
  • anchor — the API’s base URL (e.g. https://www.closient.com/products/api/v1/).
  • service-desc[0].href — the OpenAPI document URL.
  • service-desc[0].typeapplication/openapi+json.
Programmatically:
import httpx
catalog = httpx.get("https://www.closient.com/.well-known/api-catalog").json()
for entry in catalog["linkset"]:
    print(entry["anchor"], entry["service-desc"][0]["href"])
The catalog is generated from APP_API_REGISTRY in backend/apps/core/api/factory.py — that’s the source of truth if you’re inside the monorepo.

App-by-app — what each API owns

MountLabelOwns
/account/api/v1/AccountUsers, organizations, API keys, RBAC, OAuth-connected apps, whoami. Start here to identify the caller.
/agent/api/v1/AgentLLM-powered conversational endpoints (chat, search refinement, tool-use orchestration).
/advertising/api/v1/AdvertisingSponsored placements, impressions, revenue-share reporting.
/analytics/api/v1/AnalyticsScan events, search performance snapshots, brand engagement summaries. Read-heavy.
/billing/api/v1/BillingStripe subscription state, usage metrics, plan + tier endpoints. Read-only for non-owners.
/brands/api/v1/BrandsBrand records, ownership/claim flow, brand-level analytics. Write requires brands:write.
/byos/BYOS”Bring your own search” — embedded search widget endpoints (not v1 prefixed by convention).
/certifications/api/v1/CertificationsProduct certifications (organic, gluten-free, Fair Trade, …).
/compliance/api/v1/ComplianceRecalls, safety notices, FSMA 204 traceability (sibling to /epcis/api/2.0/).
/content/api/v1/ContentWagtail-backed pages, blog posts, feeds, legal pages.
/dashboard/api/v1/DashboardAggregated views consumed by the Closient web UI. Not a public-facing API.
/epcis/api/2.0/EPCIS 2.0GS1 EPCIS 2.0 event capture + query. Path mounted at /api/2.0/ per spec, not /v1/.
/integrations/api/v1/IntegrationsPOS connections (Shopify, Square, Clover, Lightspeed), webhooks.
/locations/api/v1/LocationsPhysical store/service locations with PostGIS geometry.
/notifications/api/v1/NotificationsMulti-channel notification delivery (email, Slack, SMS).
/products/api/v1/ProductsProducts (GTINs), images, validators, catalog API, categories, QR rendering.
/resolver/api/v1/ResolverGS1 Digital Link resolution + linkset queries + serial verification.
/retailers/api/v1/RetailersOffers (in-store + online), inventory sources, online-retailer integrations.
/scanner/api/v1/ScannerBarcode + product scanning, vision-extracted attributes.
/search/api/v1/SearchCatalog search, session-based local-first search, refinement.
/sustainability/api/v1/SustainabilitySustainability certifications + impact tracking.
/voice-feedback/api/v1/Voice FeedbackSpeech-to-text user feedback + reproducer playback.
The list is canonical at backend/apps/core/api/factory.py:APP_API_REGISTRY. When that list changes, the catalog updates automatically; you don’t need to re-grep.

Find an endpoint across the 22 APIs

Three strategies, fastest first:

1. Browse Mintlify docs

Interactive HTML docs aggregate every per-app OpenAPI spec at https://docs.closient.com. Search the sidebar by resource name — “product”, “brand”, “offer”, “recall” — and you’ll get the canonical endpoint URL with auth, parameters, and response schemas.

2. Fetch the OpenAPI doc directly

For machine consumption (SDK generation, MCP tool registration), grab the per-app spec straight from the catalog and parse it:
spec = httpx.get(
    "https://www.closient.com/products/api/v1/openapi.json"
).json()
for path, methods in spec["paths"].items():
    for verb, op in methods.items():
        print(verb.upper(), path, "—", op.get("summary"))
Every per-app spec follows the same shape (Django Ninja → OpenAPI 3.1).

3. Search the linkset

The catalog itself is linkset-shaped, so you can grep through anchor and service-desc.href to find candidate apps before fetching their specs. Useful in an MCP / tool-use context where dropping every spec into a prompt is wasteful.

Cross-cutting conventions (apply to every per-app API)

Authentication

Every API accepts the same three auth mechanisms; pick one:
MechanismHeader / cookie
API keyX-API-Key: csb_<body>_<crc32>
OAuth 2.0 access tokenAuthorization: Bearer <token>
Session (browser only)Django sessionid cookie
Endpoints that need no auth (catalog search, public resolver, well-known endpoints) declare auth=None in the OpenAPI spec and accept anonymous calls subject to a tighter IP-based throttle.

Pagination

List endpoints use limit/offset pagination (cursor pagination is NOT in use):
GET /products/api/v1/products?limit=50&offset=100
Response envelope:
{
  "items": [...],
  "count": 50,
  "total": 1234,
  "limit": 50,
  "offset": 100
}
Defaults: limit=25, max limit=100. Implemented by the shared apps.core.api.pagination.LimitOffsetPagination.

Error envelope (RFC 9457 Problem Details)

All errors return application/problem+json:
{
  "type": "https://www.closient.com/problems/forbidden",
  "title": "Forbidden",
  "status": 403,
  "detail": "User does not have brands:write scope on this token.",
  "instance": "/brands/api/v1/brands/abc123"
}
type is a stable URI (you can build clients that switch on it); title is human-readable; detail may include user-context information. Wired by apps.core.api.exceptions.register_error_handlers.

Rate-limit headers

Every response carries IETF RateLimit-* headers:
HeaderValue
RateLimit-PolicyAll active windows, e.g. 300;w=60, 10000;w=86400.
RateLimit-LimitQuota for the most-restrictive currently-active window.
RateLimit-RemainingRequests left in that window.
RateLimit-ResetSeconds until that window resets (relative; clock-skew safe).
Legacy X-RateLimit-* aliases are also emitted; X-RateLimit-Reset keeps the absolute Unix-timestamp shape for back-compat. Implemented in apps.core.api.throttling. Default: 300/min, 10k/day per key.

Idempotency

Mutating endpoints accept Idempotency-Key headers where the operation is naturally idempotent (POSTs that look like upserts, batch ingest endpoints). The key is opaque to Closient; same key + same body returns the original response. Check the per-endpoint OpenAPI description for the explicit Idempotency-Key parameter declaration before relying on it — not every POST is idempotent.

Empathy contract

Every Field() in every per-app schema carries a description= (or auto-pipes from the model’s help_text via ModelDocumentedSchema), and enum-shaped names are typed as StrEnums with the values declared on the schema. SDK generators get a real enum constraint instead of a bare string. See backend/apps/core/CLAUDE.md “API Empathy” for the internal contract.

OpenAPI specs are versioned per app

When an app evolves a breaking change, expect a /api/v2/ mount alongside /api/v1/. Today only EPCIS 2.0 lives outside the v1 convention (it sits at /api/2.0/ to match the GS1 EPCIS spec naming). There is no global /v1/.

Cross-app patterns to recognise

”List then detail”

For most resources, list endpoints return a slim representation; detail endpoints return the full one:
GET /products/api/v1/products       → ProductListItem (slim)
GET /products/api/v1/products/{id}  → ProductDetail   (full)
Don’t filter the list response client-side hoping to find a field — fetch the detail endpoint or use the documented query parameters.

Short IDs in URLs

Public-facing resources use a 22-character ShortUUIDField for both PKs and URL paths (see apps.core.fields.ShortUUIDField):
GET /brands/api/v1/brands/4Vh87cAnSyrSt5KQ8s9hkF
Short IDs are accepted in both shortuuid and full-UUID form; the URL converter normalizes. New code emits the short form.

Scoped to organization

Resources owned by an organization (Products, Brands, Offers, Locations, EPCIS events, …) are filtered by the caller’s organization membership. Cross-org reads return 404 Not Found rather than 403, to avoid leaking existence.

Webhooks vs polling

Closient prefers webhooks over polling for state changes. Subscribe via /notifications/api/v1/webhooks (signed with HMAC-SHA256). Endpoints that emit events are documented in each per-app OpenAPI spec; common ones: scanner events, recall notices, offer changes, EPCIS captures.

Putting it all together

A typical agent boot sequence:
  1. Hit /.well-known/api-catalog to learn what’s available.
  2. Hit /.well-known/openid-configuration to learn how to auth.
  3. Run closient-api-quickstart to register / authenticate.
  4. GET /account/api/v1/whoami to confirm the token’s identity.
  5. Walk per-app OpenAPI specs from the catalog to bind tools.
Once tools are bound, the per-workflow skills (local-product-search, resolve-gtin, claim-brand, capture-epcis-event, …) tell the agent what to do with them.
  • closient-api-quickstart — auth, scopes, first call.
  • decode-gs1-ai, build-gs1-digital-link — GS1 identifier mechanics.
  • local-product-search, resolve-gtin, check-product-availability — search + product depth.
  • claim-brand, onboard-retailer — onboarding workflows.
  • capture-epcis-event, query-epcis-events, manage-recall, check-fsma-204-readiness — supply-chain and compliance.
  • brand-scan-summary, brand-search-demand, brand-retail-footprint — brand analytics.

Authoritative references

  • RFC 9727 — API Catalog / Linkset. https://datatracker.ietf.org/doc/html/rfc9727
  • RFC 9457 — Problem Details for HTTP APIs.
  • IETF RateLimit-* headers (informed governor draft).
  • OpenAPI 3.1 spec — generated docs at https://docs.closient.com.
  • Closient internal: backend/apps/core/api/factory.py, backend/apps/core/api/pagination.py, backend/apps/core/api/throttling.py, backend/apps/core/api/exceptions.py.