yDrink Data API
Your yDrink data in your own systems, whenever you want it: the same datasets as our data feeds, with what changed and when.
Getting started
1. Your yDrink contact sends a one-time link to your key. Open it, press Show my key, and keep the key somewhere safe, like a secrets manager. It's shown once.
2. Send it on every request:
curl -H "Authorization: Bearer ydk_live_..." https://api.ydr.ink/v1/status
3. /v1/status lists the datasets you get, the periods each holds and your current version. Pull each dataset once, keep the version, and from then on pull only what changed (Staying in sync).
Keys and IP limits
Keys belong to your company, and you can have several (say one for production, one for testing). A key can be limited to your servers' IPs or ranges; ask your yDrink contact to set them. To replace a key, we send a new link, and the old key keeps working for a week after you open it, so you can switch without downtime. If a key gets out, tell us and we'll turn it off at once.
Staying in sync
Every response carries version (and the header X-Data-Version). The version goes up when your data is rebuilt and something in it changed.
GET /v1/changes?since=1041
{"version": 1077, "since": 1041, "full_refresh": false, "datasets": {
"brand_monthly": {"full_refresh": false, "periods": ["2025-10-31", "...", "2026-09-30"], "from": "2025-10", "to": "2026-09"},
"brand_weekly": {"full_refresh": false, "periods": ["202639", "202640", "202641", "202642"], "from": "202639", "to": "202642"},
"accounts": {"full_refresh": false, "changed": true, "pull": "/v1/accounts?changed_since=1041"}}}
For each dataset, delete the listed periods on your side and pull them again with from and to. For accounts and merges, pull the rows changed since your version. Then keep the new version. When a dataset says full_refresh: true, pull all of that dataset again: it's new to you (say, a dataset just added to your service), its history was corrected, or since is 0. The top-level full_refresh is true when any dataset is. Usually the newest month plus the 11 before it, and the newest weeks, change with each update.
Apply merges too: /v1/accounts/merges lists accounts found to be the same place. Move your history from merged_id to surviving_id.
Dates and periods
Monthly rows carry sales_date, the last day of the month: 2026-09-30. Weekly rows carry yearweek, like 202642; weeks start on Sunday. In from and to, give months as 2026-09 and weeks as 202642.
Paging and CSV
Each response is one page of up to about 10000 rows. When there's more, next_cursor (and the header X-Next-Cursor) holds a cursor: send it back as ?cursor= with the same other parameters for the next page, until it's null. For CSV, add ?format=csv or send Accept: text/csv; the cursor is then only in X-Next-Cursor.
Limits and headers
- Requests a minute, per key (usually 60).
- Rows a day for your company, reset at midnight Central. It's generous: about 100 times all your data.
- Requests at once for your company (usually 2).
Every answered response has X-RateLimit-Limit and X-RateLimit-Remaining (rows today) and X-RateLimit-Reset. Past 80% of the day's rows, pages are half size and responses carry a Warning header. A refused request gets 429 and Retry-After. Every response has X-Request-Id: quote it to support. /v1/usage shows your last 30 days.
Errors
Errors are JSON: {"error": {"code": "quota", "message": "...", "request_id": "..."}}. Match on code.
| Code | Status | What it means |
|---|---|---|
bad_key | 401 | No key, or a key that doesn't work (mistyped, replaced, expired or turned off). |
ip_not_allowed | 403 | The key can't be used from this IP. yDrink adds IPs to a key. |
paused | 403 | yDrink paused this key or your API access. |
no_service | 403 | Your API service isn't active. |
not_included | 403 | The dataset isn't part of your service. |
not_found | 404 | No such endpoint. |
bad_period | 400 | from or to isn't a month (YYYY-MM) or week (YYYYWW). |
bad_parameter | 400 | A parameter isn't valid; the message says which. |
bad_cursor | 400 | The cursor isn't from this dataset or query. Start again without one. |
bad_version | 400 | changed_since is older than the change tracking. Pull everything once. |
no_data_set | 409 | Your brand data isn't set up or published yet. |
rate_limited | 429 | Too many requests this minute on this key. See Retry-After. |
quota | 429 | Your company's rows for today are used up. Resets at midnight Central. |
concurrent | 429 | Too many requests at once for your company. Retry after a few seconds. |
error | 500 | Something went wrong on our side. Quote the request_id to support. |
Endpoints
Status
GET /v1/status
Your datasets (included or not, and why), the periods each holds and when it was last updated, your version, product types and limits.
What changed
GET /v1/changes?since=<version>
Every period that changed since a version, per dataset. See Staying in sync.
Your usage
GET /v1/usage
Your requests, refusals and rows by day for the last 30 days, and your limits.
Products
GET /v1/products · Every API client.
Your products: every product in your brand data, with its brand, label, size and categories.
cursor: the last page'snext_cursorformat=csv(orAccept: text/csv) for CSV
| Field | Type | What it is |
|---|---|---|
product_id | integer | yDrink's internal product id |
brand | string | Major brand name: Crown Royal |
label | string | Major label name: Crown Royal Regal Apple |
product | string | yDrink's lowest product description; often the same as label |
product_size | string | Bottle size: 750ML, 1L, 12OZ |
product_type | string | Liquor, Wine, Beer or N/A |
product_category | string | yDrink main category: Tequila, Whiskey, White, Red |
product_sub_category | string | yDrink's lower category: Anejo, Scotch, Chardonnay, Pinot Noir |
product_price_level | string | Price point: Value, Mid, Premium, Super, Luxury |
product_per_9l_case | number | Bottles in a 9-liter case |
Brand shipments, monthly
GET /v1/brand/monthly · Every API client.
Your products sold into each on-premise account, by month.
cursor: the last page'snext_cursorformat=csv(orAccept: text/csv) for CSVfrom,to: months, like2026-09establishment_id: up to 1000 ids, comma separated
| Field | Type | What it is |
|---|---|---|
establishment_id | integer | yDrink's internal establishment (account) id |
product_id | integer | yDrink's internal product id |
units | integer | Bottles sold into the account |
cases | number | 9-liter cases sold into the account |
sales_date | date | The month, as its last day: 2026-09-30 |
Brand shipments, weekly
GET /v1/brand/weekly · Every API client.
Your products sold into each on-premise account, by week.
cursor: the last page'snext_cursorformat=csv(orAccept: text/csv) for CSVfrom,to: weeks, like202642establishment_id: up to 1000 ids, comma separated
| Field | Type | What it is |
|---|---|---|
establishment_id | integer | yDrink's internal establishment (account) id |
product_id | integer | yDrink's internal product id |
units | integer | Bottles sold into the account |
cases | number | 9-liter cases sold into the account |
yearweek | string | The week, as YYYYWW: 202642. Weeks start on Sunday |
Accounts
GET /v1/accounts · Every API client.
Every on-premise account by yDrink id, with its chain and segmentation.
cursor: the last page'snext_cursorformat=csv(orAccept: text/csv) for CSVestablishment_id: up to 1000 ids, comma separatedchanged_since: a version, for only what changed since
| Field | Type | What it is |
|---|---|---|
establishment_id | integer | yDrink's internal establishment (account) id |
tdlinx_code | string | Nielsen's account id. Only for clients with TDLinx access |
coverage_indicator | integer | 0 no coverage, 1 monthly coverage, 2 weekly coverage |
name | string | Account name |
chain | string | Chain name |
corporate | string | Corporation or chain owner |
address | string | Street address: 123 Main St |
city | string | City: Austin |
zip | string | 5-digit zip code: 78756 |
county | string | County: Travis |
state | string | State: TX |
segment | string | Channel: Dining, Bar/Nightclub |
sub_segment | string | Sub channel: Casual, Sports Bar |
cuisine | string | Food type: American, Cajun |
Account merges
GET /v1/accounts/merges · Every API client.
Accounts found to be the same place: the old id and the id it was merged into. Move your history from merged_id to surviving_id.
cursor: the last page'snext_cursorformat=csv(orAccept: text/csv) for CSVchanged_since: a version, for only what changed since
| Field | Type | What it is |
|---|---|---|
merged_id | integer | The establishment id that no longer exists |
surviving_id | integer | The establishment id it was merged into |
merged_at | string | When it was merged |
Consumer spend
GET /v1/consumer-spend · With Integral or Consumer Spend.
Taxable alcohol dollars consumers spent at each on-premise account, by month (mixed beverage tax receipts).
cursor: the last page'snext_cursorformat=csv(orAccept: text/csv) for CSVfrom,to: months, like2026-09establishment_id: up to 1000 ids, comma separated
| Field | Type | What it is |
|---|---|---|
establishment_id | integer | yDrink's internal establishment (account) id |
liquor | integer | Taxable liquor dollars |
wine | integer | Taxable wine dollars |
beer | integer | Taxable beer dollars |
total | integer | Total taxable liquor, wine and beer dollars |
sales_date | date | The month, as its last day: 2026-09-30 |
Marketslice, monthly
GET /v1/marketslice/monthly · At the highest tier.
The whole on-premise spirits market by account and category, by month.
cursor: the last page'snext_cursorformat=csv(orAccept: text/csv) for CSVfrom,to: months, like2026-09establishment_id: up to 1000 ids, comma separated
| Field | Type | What it is |
|---|---|---|
establishment_id | integer | yDrink's internal establishment (account) id |
product_category | string | yDrink main category: Tequila, Whiskey |
product_sub_category | string | yDrink's lower category: Anejo, Scotch |
product_price_level | string | Price point: Value, Mid, Premium, Super, Luxury |
units | integer | Market (all) bottles sold into the account |
cases | number | Market (all) 9-liter cases sold into the account |
sales_date | date | The month, as its last day: 2026-09-30 |
Marketslice, weekly
GET /v1/marketslice/weekly · At the highest tier.
The whole on-premise spirits market by account and category, by week.
cursor: the last page'snext_cursorformat=csv(orAccept: text/csv) for CSVfrom,to: weeks, like202642establishment_id: up to 1000 ids, comma separated
| Field | Type | What it is |
|---|---|---|
establishment_id | integer | yDrink's internal establishment (account) id |
product_category | string | yDrink main category: Tequila, Whiskey |
product_sub_category | string | yDrink's lower category: Anejo, Scotch |
product_price_level | string | Price point: Value, Mid, Premium, Super, Luxury |
units | integer | Market (all) bottles sold into the account |
cases | number | Market (all) 9-liter cases sold into the account |
yearweek | string | The week, as YYYYWW: 202642. Weeks start on Sunday |
Field names follow the yDrink Data Integrations dictionary. Questions: your yDrink contact, or howdy@ydrink.net. Access is permitted under license. © yDrink. All rights reserved.
