A REST API for kosher CPG product images and metadata.
25,000+ studio-shot kosher CPG products. JPEG and PNG. Front and back. Nutrition facts, ingredients, hechshers with dairy/meat/pareve designations. One authenticated call away.
What you can build
🛒 Retailer product pages
Render a fresh, hi-res product image on your PDP without hosting a single asset. One GET per barcode. Add variants=front to only pay for what you display. Cache the response for 15 minutes. Done.
GET /api/v1/products/017000161563?include=images&variants=front
🖥️ Point-of-sale terminals
Barcode scanned → image + full metadata in under 300ms. Nutrition, hechshers, ingredients — everything the cashier's screen needs to render right away.
GET /api/v1/products/017000161563
📦 Marketplaces & catalog syncs
Bulk-check up to 500 barcodes per call for cheap existence + variant availability checks. Pull the full record only for the ones you're missing.
POST /api/v1/products/bulk-check
🔧 In-house tools
Multi-brand marketplaces, retail dashboards, internal tools — one canonical source, one API key, no duplicated storage across your apps.
GET /api/v1/products?ownership=Studio%20A
📊 Dashboards & billing widgets
Show your credits balance, spent-today, and rate-limit budget on your own admin UI. Both /balance and /account are free and safe to poll.
GET /api/v1/balance
Try a real request
- curl
- JavaScript
- PHP
- Python
# 1. Exchange your credentials for an access token
curl -X POST https://images.retaildigitals.com/api/v1/auth/token \
-H "Content-Type: application/json" \
-d '{"client_id":"your_client_id","api_key":"your_api_key"}'
# 2. Use the access token to fetch a product
curl https://images.retaildigitals.com/api/v1/products/017000161563 \
-H "Authorization: Bearer $ACCESS_TOKEN"
// 1. Exchange credentials for an access token
const { access_token } = await fetch(
'https://images.retaildigitals.com/api/v1/auth/token',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_id: process.env.RD_CLIENT_ID,
api_key: process.env.RD_API_KEY,
}),
}
).then((r) => r.json());
// 2. Fetch a product
const product = await fetch(
'https://images.retaildigitals.com/api/v1/products/017000161563',
{ headers: { Authorization: `Bearer ${access_token}` } }
).then((r) => r.json());
console.log(product.images.front);
<?php
// 1. Exchange credentials for an access token
$auth = json_decode(file_get_contents(
'https://images.retaildigitals.com/api/v1/auth/token',
false,
stream_context_create([
'http' => [
'method' => 'POST',
'header' => 'Content-Type: application/json',
'content' => json_encode([
'client_id' => getenv('RD_CLIENT_ID'),
'api_key' => getenv('RD_API_KEY'),
]),
],
])
), true);
// 2. Fetch a product
$product = json_decode(file_get_contents(
'https://images.retaildigitals.com/api/v1/products/017000161563',
false,
stream_context_create([
'http' => ['header' => 'Authorization: Bearer ' . $auth['access_token']],
])
), true);
echo $product['images']['front'];
import os, requests
# 1. Exchange credentials for an access token
auth = requests.post(
"https://images.retaildigitals.com/api/v1/auth/token",
json={
"client_id": os.environ["RD_CLIENT_ID"],
"api_key": os.environ["RD_API_KEY"],
},
).json()
# 2. Fetch a product
product = requests.get(
"https://images.retaildigitals.com/api/v1/products/017000161563",
headers={"Authorization": f"Bearer {auth['access_token']}"},
).json()
print(product["images"]["front"])
Response:
{
"barcode": "017000161563",
"product_meta": {
"brand": "Example Brand",
"product_name": "Example Cereal",
"bracha": "mezonos",
"kosher_for_passover": false,
"hechshers": [{ "symbol": "OU", "org": "Orthodox Union", "dairy_meat_pareve": "pareve" }]
},
"images": {
"front": "https://images.retaildigitals.com/api/v1/image/eyJi...",
"front_clean": "https://images.retaildigitals.com/api/v1/image/eyJi..."
},
"meta": {
"credits_debited": 2.6,
"credits_remaining": 4327.4,
"request_id": "req_01H8Y3G7Z8..."
}
}
Every response includes meta.credits_debited so you can verify billing against every request. Which brings us to —
The cost model in one paragraph
Every GET /products/{barcode} charges the sum of two independent parts:
credits = (per_scope_rate × metadata_scopes_returned) + (per_image_rate × image_variants_returned)
Two query parameters control both terms — set BOTH to get the cheapest call:
include=picks metadata scopes (product_meta,image_meta,images). Each ofproduct_metaandimage_metacosts oneper_scope_rate. Omit → all three, and you pay for both metadata scopes whether you use them or not.variants=picks image URLs (front,back,front_clean,back_clean). Each URL costs oneper_image_rate. Omit → every available variant of the barcode, up to 4 URLs.
Cheapest patterns:
# Text-only sync (no images) — 1× per_scope_rate
GET /api/v1/products/017000161563?include=product_meta
# One image URL — 1× per_image_rate (cheapest way to get an image)
GET /api/v1/products/017000161563?include=images&variants=front
# One image + metadata for a PDP — 1× per_scope_rate + 1× per_image_rate
GET /api/v1/products/017000161563?include=product_meta,images&variants=front
# The "everything please" default — most expensive; only use when you need it
GET /api/v1/products/017000161563
⚠️ Landmine: setting variants=front without also setting include=images still charges
you both default metadata scopes on top of the one image. You need both parameters to reach
the minimum-cost read. Verify with meta.credits_debited on every response.
Current admin-set rates live at GET /pricing — fetch once at daemon startup rather than hard-coding. Full formula + interaction matrix on the Pricing page.
Built for production
⚡ Fast
Median 180ms end-to-end for a full products.get. Signed image URLs are CDN-cacheable and typed correctly. No cold starts.
🔒 Locked down
Signed URLs. IP-bound. One-shot. HMAC-SHA-256. TLS 1.3 only. Every image traceable back to the client key that requested it — if your images end up somewhere they shouldn't, you'll know exactly whose credentials leaked.
💳 Pay for what you use
Prepaid credits — fractional, per-action pricing. Two query parameters (include= and variants=) let you skip metadata scopes and image variants you don't need, so you pay only for what you'll actually render. See the cost formula above, or full pricing →.
🧰 SDKs & tooling
Copy-paste JavaScript, PHP, and Python reference clients. Full OpenAPI 3.0 spec if you want to generate your own for Go, Rust, C#, or Java.
Next up
Get started
- Get started — create an account, issue your first key, make your first call. Five minutes.
- Authentication — deep dive on the token flow, refresh cadence, credential rotation.
- Product metadata reference — every field in the response, with real examples.
Reference
- API reference — every endpoint, every parameter, every response field
- Errors — every error code, retry policy, and support workflow
- Rate limits — per-tier limits, headers, best practices
- Pricing — credit packages, per-action costs, sample calculations
- Security — the 10-layer defense model, credential hygiene, vuln disclosure
Guides
- POS integration — per-store credentials, scan-time lookup, nightly prefetch
Elsewhere
- SDKs & libraries — reference implementations in JS, PHP, Python
- Changelog — version history + change policy