VynnAI

Documentation

Get a free key, then make your first request

Free Canadian grocery price API. Available Free plan: 500 calls a month, no card. Existing accounts may retain different terms. Free includes current prices. History requires an eligible paid plan. Prices from 82 stores across 18 grocery chains in every province, plus the Yukon and Northwest Territories. Collection is scheduled every night; price history starts March 22, 2026. Create your key in your account, then try this example from your server. Replace the placeholder with your key.

Counts checked October 23, 2026.

curl https://vynn.ai/v1/products/lookup?upc=0060383682057 \
  -H "Authorization: Bearer vynn_pk_your_key_here"

Authentication

Send your key in the Authorization: Bearer header on every request, as shown above.

Keys are server-side credentials

  • Call from your server, never from browser code. We deliberately send no CORS header on authenticated endpoints, so call them from your server.
  • Your key is shown in full exactly once, when it is created. We store only a hash and a display prefix, so we cannot recover it for you. Rotate it instead.
  • Responses to authenticated requests are private, no-store and must not be put in a shared cache.

Manage keys from your dashboard. Create or rotate a server-side key, then return here for the request contract. The public index page and the downloadable price sample need no key.

Endpoints

GET /v1/products/lookup

Resolve a UPC/GTIN to its canonical product and the latest offers observed for it by the nightly sweeps.

ParameterRequiredDescription
upcrequiredThe UPC/EAN/GTIN to look up.
provinceoptionalTwo-letter province code. Default ON.
limitoptionalMaximum offers to return.

GET /v1/prices/history

Per-SKU price series from the reference-store panel, one point per nightly observation.

product_id is a retailer SKU, not a UPC barcode. The legacy alias upc also treats its value as a SKU; it does not resolve a barcode. This route accepts upc or product_id, plus provinceand period, with no banner filter. Check each returned observation's banner before charting one retailer's history. Read the price history guide.

ParameterRequiredDescription
upcone ofMatched as a retailer-scoped SKU today — true UPC-to-SKU resolution is not yet available. Prefer product_id from a lookup or search result.
product_idone ofRetailer-scoped SKU.
provinceoptionalTwo-letter province code.
periodoptionalLookback, e.g. 90d.

GET /v1/stores

The geocoded reference-store directory the observations come from.

See which stores we track before choosing your province and grocery chain.

ParameterRequiredDescription
provinceoptionalTwo-letter province code.
banneroptionalBanner slug.
limitoptionalMaximum results.
offsetoptionalResults to skip, for paging.

Unrecognised query parameters are ignored rather than passed through, so a typo cannot change what you are billed for or what you receive.

Errors

Every error is JSON in the same shape. There is no HTML error page on /v1.

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Your plan's API allowance is used up. It resets at 2026-10-26T00:00:00Z. See https://vynn.ai/pricing for more capacity.",
    "retry_after_seconds": 3600,
    "resets_at": "2026-10-26T00:00:00Z",
    "plans_url": "https://vynn.ai/pricing"
  }
}
StatusCodeMeaning
400invalid_requestA required parameter is missing or invalid.
401missing_api_keyNo key, or a malformed Authorization header.
403invalid_api_keyThe key is unknown, revoked, or not a Vynn key.
404not_foundNo record matches that request.
405invalid_requestMethod not supported. These endpoints are GET-only; the response carries an Allow header.
429rate_limit_exceededRequest limit reached. Honour Retry-After. Exhausted plan allowances also include resets_at and plans_url.
502upstream_unavailableThe data service is unavailable. Retry shortly.

This example is an exhausted allowance at 23:00 UTC on October 25. A 429 carries Retry-After in seconds and matching retry_after_seconds. For a spent plan allowance, resets_at is the UTC reset time and plans_url links to more capacity. Burst limits carry retry guidance without those fields. If the backend cannot identify a limit or provide a valid reset, the response omits that information. A 502 means our data service, not your request; retrying is appropriate.

Rate limits

The table shows currently available plans. Existing accounts may retain different terms; check your account for its current allowance. Quotas are enforced per organization, pooled across its keys, against your plan. Daily quotas reset at the start of each UTC day; monthly quotas reset on the first of each month (UTC). Every call that reaches the data service counts, including rejected ones; requests rejected at this boundary, such as a missing parameter or malformed key, are not metered.

PlanCallsPeriod
Free500per month
Pro5,000per month
Pro 5x25,000per month
Max100,000per month
Team500,000per month
Enterprisecontract-defined (bounded)per month

Before you model on this data

  • A missing date means “not observed”, never “price unchanged”. Build observation-frequency controls.
  • SKUs are retailer-scoped. A UPC helps link equivalents across banners, but not every SKU is reliably matched.
  • Store identifiers do not bridge collection eras.
  • Read the methodology, the data limits, and the store coverage guide first. The gaps are disclosed there, not buried.