Skip to main content

Changelog

All notable changes to the Retail Digitals Image API. We follow Semantic VersioningMAJOR.MINOR.PATCH:

  • MAJOR — Breaking changes. Announced with 90 days notice minimum. Old major version remains available for 12 months after the new major ships.
  • MINOR — Backwards-compatible additions (new fields, new endpoints, new optional params). No advance notice, listed here on release day.
  • PATCH — Bug fixes, documentation improvements, non-behavioral changes.

Pricing changes follow their own policy — see Pricing → Change policy.

Deprecation policy: fields and endpoints marked deprecated are removed no sooner than 90 days after the deprecation announcement, and only in a MAJOR bump.


[Unreleased]

Coming soon

  • Go and Ruby reference clients
  • Published npm / Packagist / PyPI packages
  • WebHook support for product updates
  • Optional per-request HMAC signing (in addition to Bearer)

[1.4.0] — 2026-07-02 (evening)

Added

  • Idempotency-Key header on POST /products/bulk-check and POST /auth/revoke. Send a 20-255 char unique token to make retries safe. Replaying the same key + same body within 24 hours returns the cached response with Idempotency-Replayed: 1 header. Replaying with a different body returns 409 idempotency_key_mismatch. Recommended pattern: UUID per logical operation, or a stable per-day key for scheduled jobs.
  • updated_since query parameter on GET /products. Pass an ISO date/datetime to return only products whose updated_at is on or after that value. Combines with the existing search, min_digits, has_front, etc. filters. Ideal for incremental nightly catalog syncs — save the current time before your sync, use it as updated_since on the next run to fetch just the changes. See the POS integration guide for the full nightly-sync pattern.

Changed

  • Response headers now include X-Request-ID, X-Credits-Debited, X-Credits-Remaining, X-RateLimit-Limit-Minute/-Day, X-RateLimit-Remaining-Minute/-Day, X-RateLimit-Reset, and Content-Type: application/json; charset=utf-8 on every /api/v1/* response. Documented in the top-level info.description of the OpenAPI spec.
  • source_batch field on image_meta is now documented as open string (was enum leaking internal ops tags into public contract).

[1.3.0] — 2026-07-02 (afternoon)

Changed

  • GET /pricing now exposes the cost model explicitly. Response now includes pricing_model, formula, notes, and per-action descriptions alongside the existing actions map. The formula credits = (per_scope_rate × metadata_scopes) + (per_image_rate × image_variants) is now discoverable from a single API call — customers no longer need to reverse-engineer it from meta.credits_debited responses.

    Backwards compatible: the actions map keys and values are unchanged. Existing daemons that read actions["products.get"] and actions["products.get.per_image"] keep working; new integrators can additionally read formula / notes / descriptions to learn the model without doing arithmetic.

Documentation

  • include= parameter docs — rewritten to state the per-scope cost, explicitly call out the "omit → all three scopes billed" default, and cross-reference variants=. Old copy said only "Omit for all three" without any pricing consequence.
  • variants= parameter docs — rewritten to state that combining with include= is required for the cheapest call. Old copy left include= implicit.
  • docs/pricing.mdx cost formula callout — prominent :::tip at the top of the page shows the formula, the "cheapest for common use cases" ladder, and the double-set-both-parameters landmine that our first live customer integration hit.
  • docs/getting-started.mdx Step 4/5 flow — Step 4 now warns that the no-params default is the most expensive call. Step 5 introduces the two cost levers with a :::danger box on the "set BOTH" requirement.
  • docs/reference/product-metadata.mdx — two separate cost tables merged into one 9-row interaction matrix showing every include= × variants= combination.

[1.2.0] — 2026-07-02 (morning)

Added

  • variants= query parameter on GET /products/{barcode} — comma-separated list of image variants (front, back, front_clean, back_clean) the customer actually wants URLs for. When omitted, every available variant is returned (unchanged behavior). Pricing is per requested variant — asking for variants=front on a 4-variant product now costs 1 credit instead of 4. Invalid values return 400 bad_request.

    Backwards-compatible: integrations that don't send variants= continue to receive every variant and pay for every URL, as before.

Changed

  • The admin activity log at /admin/api-clients now surfaces the include= and variants= values each customer sent per request (stored in a new api_usage.include_scopes column). Operators can verify what the customer asked for without doing pricing arithmetic.

[1.1.0] — 2026-07-02

Added

  • GET /balance — minimal-payload shortcut for polling credit balance. Free, returns { client_id, credit_balance, tier, meta }. Use it for dashboard widgets, low-balance alerts, or pre-flight checks before an expensive call. See the API reference for the schema.

Changed

  • GET /products/{barcode} response now matches the documented schema:
    • hechshers[] fields renamed from hechsher_symbol / hechsher_org / hechsher_logo to symbol / org / logo (matches the Product metadata reference)
    • nutrition.<field> are now { amount, dv } objects instead of the parallel flat total_fat + total_fat_dv scalars the DB stored
    • ingredients.allergens is a real JSON array (was a JSON-encoded string)
    • kosher_for_passover, gluten_free, vegan, organic return real booleans (were 0 / 1 integers)
    • Internal DB columns (id, created_at, updated_at, redundant barcode) stripped from every nested object

Migration note. Existing integrations that decoded allergens with JSON.parse() should just consume it as an array now. Field renames in hechshers[] are breaking if you switched on the old prefixed names — the payload only matched the documented spec starting with this release, so treat this as the "spec-compliant" baseline going forward.

API infrastructure

  • Per-endpoint throttle on POST /auth/token and POST /auth/refresh10 requests per minute per IP (below the global 60/min for authenticated routes). Brute-forcing a raw api_key was already impractical at the client's 48-char random key length; this tightens the layer at zero cost to legitimate integrations.
  • Per-user cap on the number of active API clients (default 5, admin-configurable)
  • New self-issued clients start at 0 credits (was 100). Admin approves the initial balance top-up. Prevents credit farming via bulk client creation.
  • All API-delivered images now carry the same admin-controlled watermark used for ZIP downloads (was placeholder before). Response advertises X-Watermarked: 0/1.

[1.0.0] — Initial public release

Public launch of the Retail Digitals Image API.

Endpoints

  • POST /auth/token — exchange client_id + api_key for access + refresh tokens
  • POST /auth/refresh — rotate refresh token, get new access token
  • POST /auth/revoke — explicitly invalidate current tokens
  • GET /products/{barcode} — full product with image_meta, product_meta, images
  • HEAD /products/{barcode} — existence check
  • GET /products — paginated catalog listing with filters
  • POST /products/bulk-check — batch existence check, up to 500 barcodes
  • GET /products/{barcode}/image?variant= — 302 redirect to signed image URL
  • GET /image/{token} — signed URL delivery endpoint
  • GET /account — balance + quotas + usage snapshot
  • GET /usage — historical usage query
  • GET /health — service health
  • GET /pricing — current per-action credit prices

Auth

  • HS256-signed JWT access tokens (1 hour TTL)
  • Single-use refresh tokens with reuse detection (90-day TTL, rotated on every use)
  • Bearer scheme (Authorization: Bearer <access_token>)
  • Per-endpoint rate limits on /auth/token (10/min/IP) and /auth/refresh (30/min/IP)

Security

  • All signed image URLs are IP-bound, 15-minute TTL, single-use
  • Every delivered image carries visible + invisible per-client watermarks
  • Optional per-client IP allowlist
  • 90-day audit log queryable via /usage

Catalog

  • 25,000+ kosher CPG products at launch
  • Up to 4 image variants per product: front, back, front_clean, back_clean
  • Full structured metadata: brand, ingredients, allergens, hechshers, nutrition, bracha, etc.
  • product_meta schema documented in Product Metadata Reference

Pricing

  • Initial pricing table published — see Pricing
  • Free tier: 100 credits / month, watermark stronger, no commercial use
  • Standard tier: pay-as-you-go, no monthly base
  • Enterprise: contact sales

Known limitations

  • Response bodies uncompressed (gzip planned for 1.1.0)
  • No WebHook events (planned)
  • No mobile SDKs (roadmap Q4 2026)
  • Some products still awaiting full nutrition scan — see product_meta.nutrition for null

Version support policy

VersionStatusSupported until
1.0.0Current

We commit to supporting each MAJOR version for at least 12 months after its successor ships. During the overlap, both versions run on the same infrastructure with the same uptime SLA.