Beta

The Partner Trading API v1 is in beta — endpoints and response shapes may still change.

Developers
Cru World Wine
API v1 · REST & MCP
Your portfolio

Retrieve your portfolio

The wine you hold, by wine: where each unit is, its status, condition and cost, any listing, and each wine’s market price, lowest offer and highest bid.

GET/portfolioLIVE
Required scopeportfolio:readAuthentication requiredTry it

Query parameters

ALL OPTIONAL
PARAMETERDESCRIPTION
lwinstring · CSV · ≤ 20 Only these wines: up to 20 comma-separated 18-digit LWIN18 codes. Anything else is refused with VALIDATION_INVALID_VALUE.
wine_namestring · ≤ 100 chars Only wines whose name contains every word given, as GET /wines matches a name, such as “Lafite 2010”: one to six words of two or more characters; one-letter words are left out. Anything else is refused with VALIDATION_INVALID_VALUE.
current_location_codestring · CSV · ≤ 50 Only portfolio lines of wine stored now at any of these, as warehouse.current_location_code gives them, comma-separated, such as UK_DRAK,IB_20,ADDR_123: a Cru warehouse code (UK_DRAK, HK_KERRY, SG_TOLL, FR_DARTESS, US_NAPA), IB_ and the inbond_address_id of an inbond warehouse outside Cru, or ADDR_ and the id of your own address. Case-insensitive. Unlike deliverable_warehouse_code, it says where the wine is, not where it is delivered from. An ADDR_ code that is not one of your addresses matches nothing. Anything else is refused with VALIDATION_INVALID_VALUE.
deliverable_warehouse_codestring · CSV Only portfolio lines whose warehouse.deliverable_warehouse_code is any of these Cru warehouses, comma-separated: UK_DRAK, HK_KERRY, SG_TOLL, FR_DARTESS, US_NAPA. An unknown code is refused with VALIDATION_INVALID_VALUE.
stock_typestring · CSV Only portfolio lines of these stock types, comma-separated, such as cru,external. A stock_type is cru, external, supplier or bpo, and only a corporate supplier has the last two. Any other value is refused with VALIDATION_UNSUPPORTED_VALUE.
stock_statusstring · CSV Only portfolio lines with any of these stock_status values, comma-separated: in_stock, in_transit or due_in. Case-insensitive. It matches the stock_status each line shows, so a supplier’s own offers and its BPO stock are due_in. Any other value is refused with VALIDATION_UNSUPPORTED_VALUE.
duty_paidboolean true for only the portfolio lines whose duty is paid; false for only those whose duty is not. Omit it for both. Default: both
condition_statusstring · CSV Only portfolio lines with any of these condition_status values, comma-separated: verified, client_reserves or apd. Case-insensitive. A line with no condition_status matches none of them. Any other value is refused with VALIDATION_UNSUPPORTED_VALUE.
is_listedboolean true for only the portfolio lines listed for sale, as GET /offers gives them; false for only those that are not. Omit it for both. Default: both
limitinteger · 1–100 Number of wines to return. A larger value is refused with VALIDATION_INVALID_VALUE, not reduced. Default: 50
offsetinteger · ≥ 0 Number of wines to skip. Default: 0
Changed: holdings is now portfolio

Each wine’s holdings[] is now portfolio[], and its quantity is now total_quantity. On each line, held is now stock_type, and the value elsewhere is now external; status is now stock_status, condition is now condition_status, as on market offers, and listed is now is_listed.

Changed: one portfolio_id per line

Lines no longer have holding_ids, one HOLDING- id per unit. Each line now starts with portfolio_id, one id for the whole line. Give a listed line’s portfolio_id to GET, PATCH or DELETE /offers/{code} to read, change or remove just its units. Ids from holding_ids do not carry over.

Changed: pricing, in one currency

On each line, cost, cost_currency, listed_price and listed_currency are now pricing.cost and pricing.listing_price, in the wine’s currency: data.currency is now currency on each wine, the market’s, and wine bought or listed in another currency is converted at today’s rate. No line carries a currency of its own.

Changed: can_sell is gone

Lines no longer have can_sell: a bare false never said why. List or sell the units instead: if they can’t be sold yet, the request is refused with TRADE_REFUSED / 422, and its message says why, such as a condition check being needed.

Changed: three prices on every wine

Each wine now always has market_price, before portfolio rather than after it, so include_market_price is no longer needed: sending it still works, and changes nothing. Beside it are two new prices: lowest_offer_price, the lowest offer on Cru, and highest_bid_price, the highest bid. On each line, pricing also has four new fields after listing_price: commission_percent, commission and settlement_fee, which take it down to net_proceeds, what you receive when the line sells.

Changed: warehouse is an object

The warehouse name and warehouse_code are now warehouse.current_location and warehouse.deliverable_warehouse_code, beside two new keys, warehouse.current_location_code and warehouse.location_type. Your own wine held outside Cru has a deliverable_warehouse_code, the Cru warehouse it goes to once sold, only while it is listed.

Changed: a supplier’s own stock, and every unit once

A corporate supplier’s portfolio now includes its own offers and its stock on broking purchase orders, as stock_type supplier and bpo, which it left out before. A wine whose LWIN Cru sells as two products no longer lists each of its units twice, so its total_quantity can be lower than before.

Filters narrow each wine too

wine_name, current_location_code, deliverable_warehouse_code, stock_type, stock_status, duty_paid and condition_status combine with each other and with lwin. They choose the portfolio lines shown inside each wine, as well as which wines appear.

A corporate supplier’s own stock

A corporate supplier also sees its own offers, as stock_type supplier, and its stock on broking purchase orders, as stock_type bpo. Both are always due_in, as market offers show them: the stock reaches Cru only once it is sold. Neither has a cost. Its own offers can fill bids placed on Cru, through POST /market/bids/{code}/sell; BPO stock cannot be sold into a bid. Cru takes no commission from a supplier, and adds its margin for buyers instead, so both are listed at what the supplier is paid: pricing.listing_price and pricing.net_proceeds are each the supplier’s own price or, for BPO stock, the purchase order’s cost, and commission_percent, commission and settlement_fee are 0.0. Its own offers are in “Your warehouse”, of warehouse.location_type supplier. BPO stock is named after the purchase order’s supplier warehouse, of warehouse.location_type inbond with its IB_ current_location_code, or is in “Your warehouse” when the order names none. Both have a warehouse.deliverable_warehouse_code: the Cru warehouse they go to once sold, which for stock at the supplier’s own warehouse is the Cru warehouse in its country, as market offers show it, or null in a country with none.

Response fields

200 OK · paged

data.wines, in order of their product name, which wine_name may word differently, each with its currency — the market’s, which every amount is in: pricing, market_price, lowest_offer_price and highest_bid_price. meta.pagination counts wines.

Each item in wines[]

lwin18string

The 18-digit LWIN: wine, vintage and pack together. Match on all 18 digits.

wine_namestring | null

Cru’s name for the wine.

vintageinteger | null

The vintage year. 1000 means non-vintage.

pack_sizestring | null

Pack format, for example 6x75cl.

product_urlstring | null

The wine’s page on the Cru storefront for the market you called.

currencystring

ISO 4217 currency of every price here: the currency of the market you called. A price bought or listed in another currency is converted at today’s rate.

total_quantityinteger

Units in this wine’s portfolio lines, in total: all you hold of it, or what a filter leaves. On GET /offers, the units listed; on GET /offers/{code} and in what an offer write answers with, the units of the lines shown.

market_pricenumber | null

Cru’s market price for this wine, in its currency. Null when Cru has no price.

lowest_offer_pricenumber | null

The lowest price in Cru’s offer book for this wine, what a buyer would pay now, in its currency. Your own listings count. Null when there is no offer.

highest_bid_pricenumber | null

The highest bid on Cru for this wine, at the net price GET /market/bids quotes — what a seller receives for filling it — in its currency. Your own bids count, and so do bids your stock cannot fill: each bid’s requirements decide that. Null when there is no bid.

portfolioarray<object>

Lines of identical units, described below.

Each item in portfolio[]

portfolio_idstring

Opaque id of the line: PORTFOLIO- and 64 more characters. It is the same on every read and in every currency, and changes when the line does — when its units are listed, repriced or taken off sale, or their stock_status, condition_status or warehouse changes — but not when only its quantity does. A listed line is always inside one listing. GET, PATCH and DELETE /offers/{code} take a listed line’s id, to read, change or remove just its units.

stock_typestring

How the units are held, and so how they sell: cru (stored with Cru), external (in your own storage, sold through Cru), supplier (a corporate supplier’s own offer) or bpo (a supplier’s stock on a broking purchase order). Only a corporate supplier has the last two. Not warehouse.location_type, which says what kind of place they are in.

stock_statusstring

in_stock, in_transit or due_in. A supplier’s own offers and its BPO stock are always due_in: they reach Cru only once sold.

duty_paidboolean

Whether duty has been paid.

condition_statusstring | null

The units’ condition status: verified (Verified), client_reserves (Client Reserve) or apd (As per description).

condition_textstring | null

The written description of the units’ condition. Null when there is none.

is_listedboolean

Whether the units are listed for sale. Always true on GET /offers and GET /offers/{code}, and for a supplier’s own stock.

pricingobject

What the units cost, what they are listed at, what Cru takes and what you receive when they sell, per unit, below. Every amount is in the wine’s currency, converted at today’s rate where the wine was bought or listed in another currency, as Cru’s portfolio page converts them.

pricing.costnumber | null

What you paid per unit. Null when no cost was recorded, as for wine listed without one, for a supplier’s own stock, and when it cannot be converted.

pricing.listing_pricenumber | null

The asking price per unit while the units are listed; otherwise null. For a supplier’s own stock and BPO stock, the same as pricing.net_proceeds: Cru takes no commission from a supplier, and adds its margin for buyers instead.

pricing.commission_percentnumber | null

Cru’s commission, as a percent of pricing.listing_price: 5.0 is 5%. 0.0 for a supplier’s own stock and BPO stock, as Cru takes no commission from a supplier. Null while the line is not listed.

pricing.commissionnumber | null

Cru’s commission per unit: pricing.listing_price less pricing.commission and pricing.settlement_fee is pricing.net_proceeds, to the cent. 0.0 for a supplier’s own stock and BPO stock. Null while the line is not listed.

pricing.settlement_feenumber | null

For wine held outside Cru, the settlement fee per unit of the Cru warehouse it is sold through; 0.0 for every other stock_type. Null while the line is not listed.

pricing.net_proceedsnumber | null

What you receive per unit when the line sells, pricing.listing_price less pricing.commission and pricing.settlement_fee. Null while it is not listed. Units listed at one price can carry different commissions, so a line gives the lowest, with that unit’s commission_percent, commission and settlement_fee. For a supplier’s own offers, the supplier’s own price; for BPO stock, the purchase order’s cost.

photo_urlsarray<string>

Photos of the units in this line, on Cru’s media. [] when there are none.

quantityinteger

Units in this line.

warehouseobject

Where the wine is: its location_type, current_location, current_location_code and deliverable_warehouse_code, below.

warehouse.location_typestring | null

What kind of place it is: cru (a Cru warehouse), inbond (an inbond warehouse outside Cru), address (your own address) or supplier (a supplier’s own stock). Null when you told Cru you do not know where the wine is. Not to be confused with the line’s stock_type.

warehouse.current_locationstring | null

The name of where the wine is now, as the Cru website shows it: a warehouse's name; for wine at your own address, its street lines, which can run over several lines; “Your warehouse” for a supplier's own stock; or “Don't Know” when you told Cru you do not know where it is.

warehouse.current_location_codestring | null

Where the wine is now, as a code to give the current_location_code filter. For wine stored with Cru, the Cru warehouse’s code from GET /warehouses, the same as its deliverable_warehouse_code. For wine in an inbond warehouse outside Cru, IB_ and that warehouse’s inbond_address_id, such as IB_20: the writes and GET /warehouses/inbond/{id} take the number alone. Every inbond warehouse has one, even one GET /warehouses/inbond does not list and so may not find by its id. For wine at your own address, ADDR_ and the address’s id, such as ADDR_123: no endpoint lists address ids, so this is where to find them. Null for a supplier’s own stock, wine whose current_location is “Don't Know”, and wine stored with Cru in a warehouse with no Cru code.

warehouse.deliverable_warehouse_codestring | null

The Cru warehouse the wine can be delivered from, the code bids list as deliverable_warehouses: the one it is in or, for wine held outside Cru, the one it goes to once sold. Your own wine outside Cru has one only while it is listed. A supplier’s own stock and BPO stock have one wherever Cru has a warehouse to deliver to, which for stock at the supplier’s own warehouse is the Cru warehouse in its country, and null in a country with none. Null for wine stored with Cru in a warehouse with no Cru code, which cannot fill a bid. Given to GET /market/bids as deliverable_warehouse, it finds the bids the wine can fill.

Errors

An lwin that is not 18-digit LWIN18 codes, or more than 20 of them, returns VALIDATION_INVALID_VALUE / 422. A wine_name that is not one to six words of two or more characters, or is over 100 characters; a current_location_code that is not a Cru warehouse code, IB_ and an inbond warehouse’s id, or ADDR_ and a whole number from 1, or more than 50 of them; or a deliverable_warehouse_code that is not a Cru warehouse code returns VALIDATION_INVALID_VALUE / 422. A stock_type other than cru, external, supplier or bpo, a stock_status other than in_stock, in_transit or due_in, a duty_paid other than true or false, or a condition_status other than verified, client_reserves or apd returns VALIDATION_UNSUPPORTED_VALUE / 422. An is_listed other than true or false returns VALIDATION_UNSUPPORTED_VALUE / 422 as well. Missing or invalid credentials return AUTH_INVALID_CREDENTIALS / 401. A credential without portfolio:read gets AUTH_INSUFFICIENT_SCOPE / 403. View all error codes →

UP NEXT List your purchases

API credentials

Enter the client key and secret issued by Cru. They are kept for this browser tab’s session — a reload keeps them, closing the tab or clearing them ends them.

Credentials are never included in copied examples, and are redacted from anything the console prints back.

Request API access

Tell us who you are and what you want to build. Cru issues a client key and secret for your organisation, scoped to what you need.

Markets you trade in (choose one or more)

We use what you send here to reply about API access, and for nothing else. Cloudflare Turnstile checks the form for bots (privacy policy).