Documentation
API reference
Canadian grocery price data over HTTPS. JSON in, JSON out, documented errors, and a method you can cite.
Authentication
Send your key as a bearer token on every request:
curl https://vynn.ai/v1/products/lookup?upc=0060383682057 \
-H "Authorization: Bearer vynn_pk_your_key_here"Keys are server-side credentials
- Call from your server, never from browser code. We deliberately send no CORS header on authenticated endpoints, so a browser cannot call them — that is a feature, not a gap.
- 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 instead.
- Responses to authenticated requests are
private, no-storeand 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 observation 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.
| Parameter | Required | Description |
|---|---|---|
upc | required | The UPC/EAN/GTIN to look up. |
province | optional | Two-letter province code. Default ON. |
limit | optional | Maximum offers to return. |
GET /v1/products/search
Search the catalogue by product name or brand.
| Parameter | Required | Description |
|---|---|---|
q | required | Search text. |
limit | optional | Maximum results to return. |
province | optional | Two-letter province code, e.g. ON. |
GET /v1/prices/history
Per-SKU price series from the reference-store panel, one point per nightly observation.
| Parameter | Required | Description |
|---|---|---|
upc | one of | Matched 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_id | one of | Retailer-scoped SKU. |
province | optional | Two-letter province code. |
period | optional | Lookback, e.g. 90d. |
GET /v1/stores
The geocoded reference-store directory the observations come from.
| Parameter | Required | Description |
|---|---|---|
province | optional | Two-letter province code. |
banner | optional | Banner slug. |
limit | optional | Maximum results. |
offset | optional | Results 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": "..." } }| Status | Code | Meaning |
|---|---|---|
400 | invalid_request | A required parameter is missing or invalid. |
401 | missing_api_key | No key, or a malformed Authorization header. |
403 | invalid_api_key | The key is unknown, revoked, or not a Vynn key. |
404 | not_found | No record matches that request. |
405 | invalid_request | Method not supported. These endpoints are GET-only; the response carries an Allow header. |
429 | rate_limit_exceeded | Plan quota exceeded. Honour the Retry-After header. |
502 | upstream_unavailable | The data service is unavailable. Retry shortly. |
A 429 carries Retry-After — back off rather than retrying immediately. A 502 means our data service, not your request; retrying is appropriate.
Rate limits
Quotas are enforced per key 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 — a missing parameter, a malformed key — are not metered.
| Plan | Calls | Period |
|---|---|---|
| Free | 100 | per day |
| Pro | 10,000 | per month |
| Pro 5x | 50,000 | per month |
| Max | 200,000 | per month |
| Team | 2,000,000 | per month |
| Enterprise | contract-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 and the data limits first. The gaps are disclosed there, not buried.