Partner API
Use the Partner API to pull carbon footprint emissions data for your products into your own systems — including total emissions, a link to the full results page, and a shareable PDF report.
403 with { "code": "PLAN_REQUIRED" } — it does not return empty data, so check the status code rather than the body. Accounts on a free trial of a paid plan have full access.Authentication
All requests require your secret API key passed as a header:
x-api-key: zlch_sk_YOUR_SECRET_KEYGenerate one in Settings → Profile → Secret API Key inside your Zilch account.
zlch_live_…) and a secret key (zlch_sk_…). The publishable key is the one the carbon emissions widgetembeds in your website's HTML, so it is public by design and can only do single-SKU lookups. Every endpoint below except /api/partner/emissions-by-sku requires the secret key and returns 403 SECRET_KEY_REQUIRED if you send the publishable one.Keep the secret key server-side — in an environment variable or your secrets manager, never in front-end code, a mobile app, or a public repository. If it's ever exposed, rotate it from the same settings page; that invalidates the old key immediately and leaves your widget running.
Base URL
https://www.api.tryzilch.comEndpoints
1. All products
Returns emissions data for every assessed product in your account.
GET /api/partner/emissions-totalsRate limit: 10 requests per 24 hours — and every page counts as one request. At the 500-item maximum per page that's up to 5,000 products a day; a larger catalogue simply spreads its pages over consecutive days. See Keeping your data in sync below.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
page | integer | No | Page number (default: 1) |
items_per_page | integer | No | Results per page, max 500 (default: 100) |
skus | string | No | Comma-separated list of SKUs to filter by |
Example — all products
curl -H "x-api-key: zlch_sk_YOUR_SECRET_KEY" \
"https://www.api.tryzilch.com/api/partner/emissions-totals"Example — filter to specific SKUs
curl -H "x-api-key: zlch_sk_YOUR_SECRET_KEY" \
"https://www.api.tryzilch.com/api/partner/emissions-totals?skus=ABC-001,ABC-002"Example response
{
"success": true,
"page": 1,
"items_per_page": 100,
"total_items": 3,
"data": [
{
"product_id": "3a8f63ea-0a71-4c3e-b4c6-9a3269a6b299",
"product_name": "Recycled Tote Bag",
"sku": "RTB-001",
"supplier_id": "4f6931f7-c31a-44fa-8df0-55cdc418a218",
"total_kg_co2e": 2.41,
"emissions_breakdown": {
"total": 2.41,
"materials": 1.12,
"packaging": 0.34,
"decoration": 0.21,
"transport": 0.48,
"manufacturing": 0.26
},
"last_calculated_at": "2026-02-15T09:34:00.000Z",
"results_url": "https://app.tryzilch.com/results/3a8f63ea...?supplier_id=4f6931f7...",
"pdf_url": "https://www.api.tryzilch.com/api/pdf/4f6931f7.../3a8f63ea..."
}
]
}2. Single product by SKU
Returns emissions data for one specific product, looked up by SKU.
GET /api/partner/emissions-by-skuRate limit: 1,000 requests per SKU per 24 hours.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
sku | string | Yes | The product SKU |
Example
curl -H "x-api-key: zlch_sk_YOUR_SECRET_KEY" \
"https://www.api.tryzilch.com/api/partner/emissions-by-sku?sku=RTB-001"Example response
{
"success": true,
"data": {
"sku": "RTB-001",
"product_name": "Recycled Tote Bag",
"total_kg_co2e": 2.41,
"emissions_breakdown": {
"total": 2.41,
"materials": 1.12,
"packaging": 0.34,
"decoration": 0.21,
"transport": 0.48,
"manufacturing": 0.26
},
"last_calculated_at": "2026-02-15T09:34:00.000Z",
"results_url": "https://app.tryzilch.com/results/3a8f63ea...?supplier_id=4f6931f7...",
"pdf_url": "https://www.api.tryzilch.com/api/pdf/4f6931f7.../3a8f63ea..."
}
}Response fields
| Field | Description |
|---|---|
total_kg_co2e | Total carbon footprint in kg CO₂e |
emissions_breakdown | Emissions split across materials, packaging, decoration, transport, and manufacturing |
last_calculated_at | When the assessment was last run |
results_url | Link to the full interactive results page — safe to share publicly |
pdf_url | Link to the PDF report — stable, permanent URL safe to share or embed |
Errors return a JSON body with an error message and a machine-readable code. Branch on coderather than parsing the message — the wording may change, the codes won't.
Error responses
| Status | Code | Meaning |
|---|---|---|
| 400 | MISSING_SKU | A required parameter is missing (e.g. sku) |
| 401 | INVALID_API_KEY | The key is unknown, inactive, or was not sent |
| 403 | SECRET_KEY_REQUIRED | You sent the publishable widget key (zlch_live_…) to an endpoint that needs the secret key (zlch_sk_…) |
| 403 | PLAN_REQUIRED | Your account is on the free plan, or the subscription has lapsed |
| 404 | SKU_NOT_FOUND | No assessed product in your catalogue matches that SKU |
| 429 | RATE_LIMIT_EXCEEDED | Rate limit exceeded — the body includes limit and retry_after |
| 500 | INTERNAL_ERROR | Server error — safe to retry |
Rate limits summary
| Endpoint | Limit | Key required |
|---|---|---|
/api/partner/emissions-totals | 10 requests / 24h (each page counts) | Secret |
/api/partner/emissions-by-sku | 1,000 requests per SKU / 24h | Secret or publishable |
Limits are per API key on a rolling 24-hour window, not a calendar day. Rotating your key does not reset them.
Keeping your data in sync
Emissions figures change: assessments get revised and new emissions factors become available, which can move a product's total. If you're storing our data in your own database, run a scheduled job so what you display stays current.
Weekly or monthly is the right cadence for most setups. Assessments are revised occasionally rather than continuously, so a nightly job mostly re-fetches numbers that haven't moved. A practical pattern:
- Page through
/api/partner/emissions-totalswithitems_per_page=500to refresh your whole catalogue. Budget one request per page against the 10-per-24h limit. - For anything that needs to be fresher than that — a product page being viewed right now — use
/api/partner/emissions-by-sku, which allows 1,000 lookups per SKU per day. - Store
last_calculated_atalongside your own copy so you can tell how stale a figure is, and surface it if you show a “last updated” date.