Your app
website · widget · server
Lekhio API
tenant ID + optional key · rate-limited
5-min cache
refresh barrier
FRESHYour data
only fields you expose
How these docs work
Concepts explains the model, the Reference documents every endpoint, the Playgroundruns real requests, and Recipes are copy-paste integrations. Every example uses a live demo tenant — H7T8QPCC.
Concepts
How the API works
The API is read-only and tenant-scoped. A business decides what to share; consumers read it by tenant ID.
Tenant ID
An 8-character public code (e.g. H7T8QPCC) that identifies a business. Safe to share — it only reveals opted-in data.
Opt-in exposure
Nothing is public by default. Owners pick which collections (and even which fields) to expose from their ERP.
API keys
Optional. Sent as x-api-key, a key raises the rate limit and can read the tenant’s private collections too.
Caching
Responses are cached for 5 minutes — the “refresh barrier” — so data updates at most every 5 minutes.
Quickstart
Your first request
- 1. In your ERP, open Developer & API to find your Tenant ID and choose what to expose.
- 2. Read the tenant profile to discover what’s available:
curl "https://api.lekhio.com/api/v1/public/t/H7T8QPCC"3. Read a collection’s records — filter, sort and paginate:
curl "https://api.lekhio.com/api/v1/public/t/H7T8QPCC/products?limit=10&sort=-createdAt"Reference
Endpoints
GET /public/t/:tenantId
The tenant profile + the collections it exposes (with each collection’s public fields).
{
"success": true,
"data": {
"publicId": "H7T8QPCC",
"name": "Demo Business Co.",
"industry": "other",
"collections": [
{
"slug": "products",
"name": "Products",
"fields": [
{ "key": "name", "label": "Name", "type": "text" },
{ "key": "selling_price", "label": "Price", "type": "currency" }
]
}
]
}
}GET /public/t/:tenantId/:collectionSlug
Records from an exposed collection. Only opted-in fields are returned; each row includes an id and createdAt.
Query parameters
| search | Free-text match across text fields ?search=widget |
| where[field][op] | Filter. op ∈ eq, ne, gt, gte, lt, lte, contains, startsWith, in, nin, exists, between ?where[selling_price][gte]=100 |
| sort | Comma list; prefix - for descending ?sort=-createdAt,name |
| fields | Comma list to project a subset ?fields=name,selling_price |
| page | Page number (from 1) ?page=2 |
| limit | Rows per page (max 200, default 20) ?limit=50 |
{
"success": true,
"data": [
{ "id": "6a53…bdea", "createdAt": "2026-07-12T08:00:00Z",
"name": "Wireless mouse", "selling_price": 799 }
],
"meta": {
"page": 1, "limit": 20, "total": 4, "pages": 1,
"collection": { "slug": "products", "name": "Products" },
"fields": [ { "key": "name", "label": "Name", "type": "text" } ]
}
}Authentication
API keys (optional)
Opted-in data is public — no key needed. Add a tenant’s API key as an x-api-key header to raise the rate limit and read that tenant’s private collections. Generate keys on the ERP’s Developer page; they’re shown once.
curl "https://api.lekhio.com/api/v1/public/t/H7T8QPCC/products" \
-H "x-api-key: lk_xxxxxxxxxxxxxxxx"Limits & caching
Rate limits and the 5-minute barrier
60req / min
without an API key (per IP)
600req / min
with a valid API key
5minutes
response cache — data refreshes at most this often
Standard RateLimit-* headers are returned. When exceeded you get 429; add a key or slow down. Because reads are cached, hammering the API won’t get you fresher data — poll every 5 minutes.
Errors
Response shape & errors
Every response is { success, message, data, meta? }. On failure, success is false with a human message.
| Status | Meaning |
|---|---|
| 200 | Success. |
| 404 | Unknown tenant ID, public API disabled, or the collection isn’t exposed. |
| 429 | Rate limit exceeded — add an API key or slow down. |
| 5xx | Something went wrong on our side. Retry with backoff. |
Recipes
Copy-paste integrations
Embed a live product catalog on any site
No backend, no build step — just fetch and render.
<div id="catalog"></div>
<script>
const TENANT = "H7T8QPCC";
fetch(`https://api.lekhio.com/api/v1/public/t/${TENANT}/products?limit=12`)
.then(r => r.json())
.then(({ data }) => {
document.getElementById("catalog").innerHTML = data
.map(p => `<div class="card">${p.name} — ${p.selling_price ?? ""}</div>`)
.join("");
});
</script>Other things you can build
Storefront / price list
Publish your product catalog to a marketing site or marketplace.
Public order/tracking lookup
Expose a status collection so customers can check progress by ID.
Dashboards & sheets
Pull data into Google Sheets, Looker, or a BI tool on a 5-minute cadence.
Partner integrations
Give partners a tenant ID + key to sync your catalog into their system.
Playground
Try it live
Paste a tenant ID (try H7T8QPCC) and an optional key, then run a real request.
curl "https://api.lekhio.com/api/v1/public/t/YOUR_TENANT_ID"Or browse a tenant’s public page at /tenant.
Ready to expose your data?
Open the Developer & API page in your ERP to get your tenant ID and API keys.
Open Developer settings ↗