# Cru Trading API v1, as implemented. The source the SDKs and the Postman collection are # generated from. Change it in the same commit as the API change. openapi: 3.0.3 info: title: Cru Trading API version: 1.0.0 description: |- The Cru partner trading API as implemented: Cru's bid and offer books, the caller's own bids, offers, portfolio and trades, and the writes that trade. Every response is one envelope: status (OK or ERROR), message (for people, never branch on it), meta (version, timestamp, request_id, and pagination on paged lists) and data, with errors[] on a failure. Branch on the HTTP status and errors[].code. Paged lists take limit and offset and say meta.pagination.has_more. A partner credential (CLIENT-KEY and CLIENT-SECRET headers) writes at once and must send a reference, its idempotency key: a retry with the same reference never acts twice. A connected app (OAuth 2.0 bearer token) has its writes staged: the write answers 202 with a confirmation, and nothing happens until POST /confirmations/{code}. Amounts are plain numbers in the market's currency (1200.5 is 1,200.50), never minor units. Fields listed with x-extensible-enum may gain values: treat an unknown one as unknown, not as an error. New fields may appear in any response. contact: name: Cru World Wine url: https://developers.cruworldwine.com servers: - url: https://{market}.cruworldwine.com/api/v1 description: One host per market. A credential works on its own market only (AUTH_STORE_NOT_ALLOWED elsewhere). variables: market: default: uk enum: - uk - us - hk - sg - eu - ae - cn security: - ClientKey: [] ClientSecret: [] - OAuth: [] tags: - name: Account - name: Warehouses - name: Reference data - name: Market data - name: Your bids - name: Your offers - name: Your portfolio - name: Buy and sell - name: Your addresses - name: Confirmations paths: /ping: get: operationId: ping summary: Test authentication description: |- Confirm that your credentials work and see the account, market, currency, permissions and expiry they carry. **A simple first request.** This authenticated check returns your credential details without exposing any trading data. tags: - Account x-cru-sdk: resource: client method: ping x-cru-scope: meta:read security: - ClientKey: [] ClientSecret: [] - OAuth: - meta:read responses: '200': description: Fields returned in the data object. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/PingResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /warehouses: get: operationId: listWarehouses summary: List warehouses description: |- The five Cru warehouses wine can be delivered into: codes, addresses, bond references, delivery instructions, and whether your inbond wine sells through each. **The codes every other endpoint uses.** A bid’s deliverable_warehouses, an offer’s warehouse_code and the warehouse.deliverable_warehouse_code of a listing or a portfolio line all use these five codes, and so does the warehouse.current_location_code of wine stored in one. Warehouses outside Cru, where your wine may be stored, are GET /warehouses/inbond: an inbond_address_id is never a warehouse_code. tags: - Warehouses x-cru-sdk: resource: warehouses method: list x-cru-scope: meta:read security: - ClientKey: [] ClientSecret: [] - OAuth: - meta:read responses: '200': description: 'data.warehouses is an array, always in the same order: UK, HK, SG, FR, US. The last three fields are yours: what each warehouse means for wine you hold outside Cru.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ListWarehousesResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /warehouses/{code}: get: operationId: getWarehouse summary: Retrieve a warehouse description: 'One Cru warehouse by its code, such as UK_DRAK: name, market, address, bond references, delivery instructions, and whether your inbond wine sells through it.' tags: - Warehouses x-cru-sdk: resource: warehouses method: get x-cru-scope: meta:read security: - ClientKey: [] ClientSecret: [] - OAuth: - meta:read parameters: - name: code in: path required: true description: UK_DRAK, HK_KERRY, SG_TOLL, FR_DARTESS, US_NAPA. Case-insensitive. schema: type: string responses: '200': description: Fields returned in data.warehouse. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/GetWarehouseResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /warehouses/inbond: get: operationId: listInbondWarehouses summary: List inbond warehouses description: |- Warehouses outside Cru where your wine may be stored, by inbond_address_id: where wine held outside Cru is now, and what an inbond address points at. **Not Cru’s own warehouses.** This is the Cru website’s “Where is it now?” list. Your listings and portfolio lines in one carry IB_ and its inbond_address_id, such as IB_20, as warehouse.current_location_code. The five Cru warehouses wine is delivered into are GET /warehouses, by warehouse_code: an inbond_address_id is never a warehouse_code. tags: - Warehouses x-cru-sdk: resource: inbond_warehouses method: list x-cru-scope: meta:read security: - ClientKey: [] ClientSecret: [] - OAuth: - meta:read responses: '200': description: 'data.inbond_warehouses is an array in the order the Cru website lists them: those in GB, then FR, SG, HK and US, then everywhere else — each group by name — then any you suggested that Cru has not approved yet.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ListInbondWarehousesResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' post: operationId: suggestInbondWarehouse summary: Suggest an inbond warehouse description: |- Suggest a warehouse outside Cru that GET /warehouses/inbond does not list. Until Cru approves it, only you see it and can use its inbond_address_id. **Only with warehouses:suggest, which Cru grants.** A suggestion adds to the list every customer picks from, so Cru grants warehouses:suggest itself, on a partner credential, and never to a connected app: ask Cru to enable it. Without it, the customer emails customerservice@cruworldwine.com and Cru adds the warehouse, as the Cru website says. **Check the list first.** A warehouse Cru already lists, or one you already suggested — the same name in the same country, ignoring case and punctuation — is refused with its inbond_address_id. Five can wait for Cru at a time. **Yours alone until Cru approves it.** It is saved hidden. Until Cru approves it, it is in your GET /warehouses/inbond with pending true, and its inbond_address_id works for you — for wine held outside Cru, or an inbond address — and nobody else. To save an inbond address there, give its street, city and postcode. tags: - Warehouses x-cru-sdk: resource: inbond_warehouses method: suggest x-cru-scope: warehouses:suggest security: - ClientKey: [] ClientSecret: [] - OAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SuggestInbondWarehouseRequest' x-cru-action: inbond_warehouse.suggest responses: '201': description: 'Fields returned in data: what was done, and the warehouse.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Idempotent-Replayed: $ref: '#/components/headers/Idempotent-Replayed' content: application/json: schema: $ref: '#/components/schemas/SuggestInbondWarehouseResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /warehouses/inbond/{id}: get: operationId: getInbondWarehouse summary: Retrieve an inbond warehouse description: 'One inbond warehouse by its inbond_address_id: its name, company, address, phone, London City Bond site code, and whether it is bonded.' tags: - Warehouses x-cru-sdk: resource: inbond_warehouses method: get x-cru-scope: meta:read security: - ClientKey: [] ClientSecret: [] - OAuth: - meta:read parameters: - name: id in: path required: true description: The inbond_address_id, from GET /warehouses/inbond. schema: type: integer responses: '200': description: Fields returned in data.inbond_warehouse. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/GetInbondWarehouseResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /wines: get: operationId: searchWines summary: Search wines description: |- Find wines by name and get their LWIN18 codes, with producer, region, pack size, product page, Cru’s market price and the best bids and offers. **Start here to find an LWIN18.** Every other endpoint identifies a wine by its LWIN18. This searches the way the Cru website does, best match first. **No total, and at most 100 matches.** meta.pagination has has_more but no total, and the search considers its 100 best matches: paging past them finds nothing more. Narrow the words, vintage or pack instead. **Bids and offers come with market:read.** A credential that also holds market:read gets each wine’s best five bids and five offers, from the books rather than the search. With wines:read alone, the wine comes without those two keys. tags: - Reference data x-cru-sdk: resource: wines method: search paged: true x-cru-scope: wines:read security: - ClientKey: [] ClientSecret: [] - OAuth: - wines:read parameters: - name: q in: query required: true description: 'Words from the wine name, such as “Petrus Pomerol”: one to six words of two or more characters.' schema: type: string maxLength: 100 - name: vintage in: query required: false description: Only this vintage. schema: type: integer minimum: 1800 maximum: 2100 - name: pack_size in: query required: false description: 'Only this pack, written as bottles x size: 12x75cl, 6x150cl.' schema: type: string - name: limit in: query required: false description: Number of wines to return. A larger value is refused with VALIDATION_INVALID_VALUE, not reduced. schema: type: integer minimum: 1 maximum: 50 default: 25 - name: offset in: query required: false description: Number of wines to skip. schema: type: integer minimum: 0 default: 0 responses: '200': description: data.wines, and data.currency — the currency of every price in them. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/SearchWinesResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /wines/{lwin18}: get: operationId: getWine summary: Retrieve a wine description: |- One wine by LWIN18: producer, country, region, critic score, drinking window, market price, last trade, and every bid and offer on it. **Every level of both books.** With market:read as well as wines:read, the wine carries all its bids and offers — empty lists when it has none. The wine is returned either way. tags: - Reference data x-cru-sdk: resource: wines method: get x-cru-scope: wines:read security: - ClientKey: [] ClientSecret: [] - OAuth: - wines:read parameters: - name: lwin18 in: path required: true description: The wine’s LWIN18. Find one by name with GET /wines. schema: type: string pattern: ^[0-9]{18}$ responses: '200': description: 'Fields returned in data.wine: every search field, then these.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/GetWineResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /market: get: operationId: listMarket summary: List the market description: |- Both sides of Cru’s market in one call: every wine with a bid or an offer, each with its bids and its offers. **Both books, one entry per wine.** Bids are net — what a seller receives. Offers are gross — what a buyer pays. They are the same objects as /market/bids and /market/offers, read from the same books. **Either side can be empty.** A wine is listed when it has a bid or an offer, so one of its two lists is often empty. Wines come by LWIN18, ascending, and pagination counts wines. tags: - Market data x-cru-sdk: resource: market method: list paged: true x-cru-scope: market:read security: - ClientKey: [] ClientSecret: [] - OAuth: - market:read parameters: - name: limit in: query required: false description: Number of wines to return. A larger value is refused with VALIDATION_INVALID_VALUE, not reduced. schema: type: integer minimum: 1 maximum: 250 default: 100 - name: offset in: query required: false description: Number of wines to skip. schema: type: integer minimum: 0 default: 0 - name: lwin in: query required: false description: 'Only these wines: up to 20 comma-separated 18-digit LWIN18 codes. One that is not 18 digits is refused with VALIDATION_INVALID_VALUE.' style: form explode: false schema: type: array items: type: string maxItems: 20 - name: depth in: query required: false description: 'How many bids and how many offers to return per wine, best first: bids in book order, offers cheapest first. Omit it for every level. Default: every level.' schema: type: integer minimum: 1 - name: include_market_price in: query required: false description: Add market_price — Cru’s market price for the wine, as a number — to each wine. schema: type: boolean default: false - name: include_last_trade in: query required: false description: Add last_trade — the last traded price and when — to each wine. schema: type: boolean default: false responses: '200': description: Each item in data.markets carries the wine, its bids and its offers. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ListMarketResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /market/wines/{lwin18}: get: operationId: getMarketWine summary: Retrieve the market for one wine description: |- Both sides of the market on one wine, by LWIN18: its bids and its offers in one object, without paging. **One entry of GET /market.** Bids are net — what a seller receives. Offers are gross — what a buyer pays. To filter either side by price or stock, use the wine’s /bids or /offers instead. **An empty side is an empty list.** A wine Cru knows is always described, even with nothing on either side: bids and offers are then empty lists. Only a wine Cru does not know is NOT_FOUND / 404. tags: - Market data x-cru-sdk: resource: market method: get_wine x-cru-scope: market:read security: - ClientKey: [] ClientSecret: [] - OAuth: - market:read parameters: - name: lwin18 in: path required: true description: The wine’s LWIN18. Find one by name with GET /wines. schema: type: string pattern: ^[0-9]{18}$ - name: depth in: query required: false description: 'How many bids and how many offers to return per wine, best first: bids in book order, offers cheapest first. Omit it for every level. Default: every level.' schema: type: integer minimum: 1 - name: include_market_price in: query required: false description: Add market_price — Cru’s market price for the wine, as a number — to each wine. schema: type: boolean default: false - name: include_last_trade in: query required: false description: Add last_trade — the last traded price and when — to each wine. schema: type: boolean default: false responses: '200': description: data.market is one wine, exactly as an item of GET /market. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/GetMarketWineResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /market/bids: get: operationId: listMarketBids summary: List market bids description: |- Explore Cru’s live bid book: what buyers will pay for each wine, net of commission, and the stock each bid accepts. **A bid is an opportunity to sell.** Bid prices are net of Cru’s commission: what a seller receives. Read the requirements on each bid to see which stock can fill it. **Pagination counts wines, not bids.** limit, offset and total refer to wines. Each wine carries every bid on it unless you set depth. **Book order puts Cru’s own bids first.** Wines with a Cru bid come first, newest first, then by best bid. Within a wine, Cru’s bids lead, then the rest highest first — so depth=1 is not always the best price. tags: - Market data x-cru-sdk: resource: market method: list_bids paged: true x-cru-scope: market:read security: - ClientKey: [] ClientSecret: [] - OAuth: - market:read parameters: - name: limit in: query required: false description: Number of wines to return. A larger value is refused with VALIDATION_INVALID_VALUE, not reduced. schema: type: integer minimum: 1 maximum: 250 default: 100 - name: offset in: query required: false description: Number of wines to skip. schema: type: integer minimum: 0 default: 0 - name: lwin in: query required: false description: 'Only these wines: up to 20 comma-separated LWIN18 codes. The books do not check the format, so a code that is not an LWIN18 simply matches nothing.' style: form explode: false schema: type: array items: type: string maxItems: 20 - name: wine_name in: query required: false description: Only wines whose name contains every word given, such as “Lafite 2010”. One to six words of two or more characters. schema: type: string maxLength: 100 - name: min_price in: query required: false description: Lowest price to include, inclusive, in whole units of the market’s currency — 1200 is 1,200.00. Compared with the net bid price. schema: type: integer minimum: 0 - name: max_price in: query required: false description: Highest price to include, inclusive, in whole units of the market’s currency — 1200 is 1,200.00. Compared with the net bid price. schema: type: integer minimum: 0 - name: depth in: query required: false description: 'How many bids to return per wine, in book order — Cru’s own bids first, so depth=1 is not always the highest price. Omit it for every bid. Default: every level.' schema: type: integer minimum: 1 - name: landed_stock_only in: query required: false description: 'true for only bids that require stock that has already landed; false for only bids that do not. Omit it for both. Default: both.' schema: type: boolean - name: deliverable_warehouse in: query required: false description: 'Only bids that stock in any of these warehouses could fill: UK_DRAK, HK_KERRY, SG_TOLL, FR_DARTESS, US_NAPA. Case-insensitive. Pass a portfolio line’s warehouse.deliverable_warehouse_code to see the bids it can fill.' style: form explode: false schema: type: array items: type: string enum: - UK_DRAK - HK_KERRY - SG_TOLL - FR_DARTESS - US_NAPA maxItems: 5 - name: include_market_price in: query required: false description: Add market_price — Cru’s market price for the wine, as a number — to each wine. schema: type: boolean default: false - name: include_last_trade in: query required: false description: Add last_trade — the last traded price and when — to each wine. schema: type: boolean default: false responses: '200': description: Each item in data.markets carries the wine and its nested bids. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ListMarketBidsResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /market/bids/{code}: get: operationId: getMarketBid summary: Retrieve a market bid description: |- Retrieve one live bid by its opaque code, with the wine, net price, quantity and fulfilment requirements in one object. **Reconfirm before you act.** A missing, expired or malformed bid returns the same BID_NOT_FOUND / 404. Your own bids are returned, with is_own_bid set. tags: - Market data x-cru-sdk: resource: market method: get_bid x-cru-scope: market:read security: - ClientKey: [] ClientSecret: [] - OAuth: - market:read parameters: - name: code in: path required: true description: The opaque code of a bid in GET /market/bids. URL-encode it as a single path segment. schema: type: string responses: '200': description: 'Fields returned in data.bid: the wine and the bid together.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/GetMarketBidResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /market/wines/{lwin18}/bids: get: operationId: getMarketWineBids summary: List bids on one wine description: |- Every live bid on one wine, by LWIN18, as a single market: the bid book’s shape and filters, without paging. **No bids is an empty list, not a 404.** When the wine has no live bids — or your filters remove them all — the answer is 200 with bids: [], and the wine is still described. Only a wine Cru does not know is NOT_FOUND / 404. tags: - Market data x-cru-sdk: resource: market method: get_wine_bids x-cru-scope: market:read security: - ClientKey: [] ClientSecret: [] - OAuth: - market:read parameters: - name: lwin18 in: path required: true description: The wine’s LWIN18. Find one by name with GET /wines. schema: type: string pattern: ^[0-9]{18}$ - name: min_price in: query required: false description: Lowest price to include, inclusive, in whole units of the market’s currency — 1200 is 1,200.00. Compared with the net bid price. schema: type: integer minimum: 0 - name: max_price in: query required: false description: Highest price to include, inclusive, in whole units of the market’s currency — 1200 is 1,200.00. Compared with the net bid price. schema: type: integer minimum: 0 - name: depth in: query required: false description: 'How many bids to return per wine, in book order — Cru’s own bids first, so depth=1 is not always the highest price. Omit it for every bid. Default: every level.' schema: type: integer minimum: 1 - name: landed_stock_only in: query required: false description: 'true for only bids that require stock that has already landed; false for only bids that do not. Omit it for both. Default: both.' schema: type: boolean - name: deliverable_warehouse in: query required: false description: 'Only bids that stock in any of these warehouses could fill: UK_DRAK, HK_KERRY, SG_TOLL, FR_DARTESS, US_NAPA. Case-insensitive. Pass a portfolio line’s warehouse.deliverable_warehouse_code to see the bids it can fill.' style: form explode: false schema: type: array items: type: string enum: - UK_DRAK - HK_KERRY - SG_TOLL - FR_DARTESS - US_NAPA maxItems: 5 - name: include_market_price in: query required: false description: Add market_price — Cru’s market price for the wine, as a number — to each wine. schema: type: boolean default: false - name: include_last_trade in: query required: false description: Add last_trade — the last traded price and when — to each wine. schema: type: boolean default: false responses: '200': description: data.market is one market, exactly as an item of the bid book. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/GetMarketWineBidsResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /market/offers: get: operationId: listMarketOffers summary: List market offers description: |- Explore Cru’s offer book: wines for sale on the market you call and their gross asking prices, cheapest first. **An offer is an opportunity to buy.** Offer prices are gross: what a buyer pays. The book covers the market you call, in its currency. **Pagination counts wines, not offers.** limit, offset and total refer to wines, ordered by their cheapest offer. Each wine carries its offers, cheapest first. **Refreshed by Cru’s market index.** The offer book, with each offer’s status and eta, is rebuilt by Cru’s market index rather than on every change, so it can trail the live market. Re-read an offer before acting on it. tags: - Market data x-cru-sdk: resource: market method: list_offers paged: true x-cru-scope: market:read security: - ClientKey: [] ClientSecret: [] - OAuth: - market:read parameters: - name: limit in: query required: false description: Number of wines to return. A larger value is refused with VALIDATION_INVALID_VALUE, not reduced. schema: type: integer minimum: 1 maximum: 250 default: 100 - name: offset in: query required: false description: Number of wines to skip. schema: type: integer minimum: 0 default: 0 - name: lwin in: query required: false description: 'Only these wines: up to 20 comma-separated LWIN18 codes. The books do not check the format, so a code that is not an LWIN18 simply matches nothing.' style: form explode: false schema: type: array items: type: string maxItems: 20 - name: min_price in: query required: false description: Lowest price to include, inclusive, in whole units of the market’s currency — 1200 is 1,200.00. Compared with the gross offer price. schema: type: integer minimum: 0 - name: max_price in: query required: false description: Highest price to include, inclusive, in whole units of the market’s currency — 1200 is 1,200.00. Compared with the gross offer price. schema: type: integer minimum: 0 - name: depth in: query required: false description: 'How many offers to return per wine, cheapest first. Omit it for every offer. Default: every level.' schema: type: integer minimum: 1 - name: include_market_price in: query required: false description: Add market_price — Cru’s market price for the wine, as a number — to each wine. schema: type: boolean default: false - name: include_last_trade in: query required: false description: Add last_trade — the last traded price and when — to each wine. schema: type: boolean default: false responses: '200': description: Each item in data.markets carries the wine and its nested offers. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ListMarketOffersResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /market/offers/{code}: get: operationId: getMarketOffer summary: Retrieve a market offer description: 'Retrieve one offer by its opaque code: the wine, its gross price, quantity, stock status, ETA, duty status, condition and warehouse.' tags: - Market data x-cru-sdk: resource: market method: get_offer x-cru-scope: market:read security: - ClientKey: [] ClientSecret: [] - OAuth: - market:read parameters: - name: code in: path required: true description: The opaque code of an offer in GET /market/offers. URL-encode it as a single path segment. schema: type: string responses: '200': description: 'Fields returned in data.offer: the wine and the offer together.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/GetMarketOfferResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /market/wines/{lwin18}/offers: get: operationId: getMarketWineOffers summary: List offers on one wine description: |- Every offer on one wine, by LWIN18, cheapest first, as a single market: the offer book’s shape and filters, without paging. **No offers is an empty list, not a 404.** When the wine has no offers — or your filters remove them all — the answer is 200 with offers: [], and the wine is still described. Only a wine Cru does not know is NOT_FOUND / 404. **Refreshed by Cru’s market index.** Offers, with their status and eta, come from the same index as the offer book, so they can trail the live market. Re-read an offer before acting on it. tags: - Market data x-cru-sdk: resource: market method: get_wine_offers x-cru-scope: market:read security: - ClientKey: [] ClientSecret: [] - OAuth: - market:read parameters: - name: lwin18 in: path required: true description: The wine’s LWIN18. Find one by name with GET /wines. schema: type: string pattern: ^[0-9]{18}$ - name: min_price in: query required: false description: Lowest price to include, inclusive, in whole units of the market’s currency — 1200 is 1,200.00. Compared with the gross offer price. schema: type: integer minimum: 0 - name: max_price in: query required: false description: Highest price to include, inclusive, in whole units of the market’s currency — 1200 is 1,200.00. Compared with the gross offer price. schema: type: integer minimum: 0 - name: depth in: query required: false description: 'How many offers to return per wine, cheapest first. Omit it for every offer. Default: every level.' schema: type: integer minimum: 1 - name: include_market_price in: query required: false description: Add market_price — Cru’s market price for the wine, as a number — to each wine. schema: type: boolean default: false - name: include_last_trade in: query required: false description: Add last_trade — the last traded price and when — to each wine. schema: type: boolean default: false responses: '200': description: data.market is one market, exactly as an item of the offer book. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/GetMarketWineOffersResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /photos/{id}: get: operationId: getPhoto summary: Retrieve a photo description: |- One photo of a wine on offer, as the image. It needs no credentials, so the photo_urls that link here work in an tag. **Only photos of offers in the book.** Once the offer has left the book, its photo links return NOT_FOUND / 404. tags: - Market data x-cru-sdk: resource: photos method: get security: [] parameters: - name: id in: path required: true description: 'Opaque: PHOTO- and 43 more characters. Use the links photo_urls gives you.' schema: type: string responses: '200': description: The photo. content: image/jpeg: schema: type: string format: binary image/png: schema: type: string format: binary image/webp: schema: type: string format: binary '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /bids: get: operationId: listBids summary: List your bids description: |- Your own bids on every Cru site, newest first — the live ones unless you ask for others — priced in your market’s currency, with what matched and its orders. **Live bids only, unless you ask.** Without status, only live bids come back. Name the ones you want, such as status=matched,complete, or list all six to see every bid. tags: - Your bids x-cru-sdk: resource: bids method: list paged: true x-cru-scope: bids:read security: - ClientKey: [] ClientSecret: [] - OAuth: - bids:read parameters: - name: status in: query required: false description: 'Comma-separated, e.g. matched,cancelled, from live, matched, complete, cancelled, expired and error, in any case. To see every bid, list all six: there is no all. Anything else is refused with VALIDATION_UNSUPPORTED_VALUE.' style: form explode: false schema: type: array items: type: string enum: - live - matched - complete - cancelled - expired - error default: live - name: lwin in: query required: false description: 'Only these wines: up to 20 comma-separated 18-digit LWIN18 codes.' style: form explode: false schema: type: array items: type: string maxItems: 20 - name: client_ref in: query required: false description: Only bids with this client_ref, in any case. Older bids may share one. schema: type: string maxLength: 50 - name: limit in: query required: false description: Number of bids to return. A larger value is refused with VALIDATION_INVALID_VALUE, not reduced. schema: type: integer minimum: 1 maximum: 250 default: 50 - name: offset in: query required: false description: Number of bids to skip. schema: type: integer minimum: 0 default: 0 responses: '200': description: data.bids, newest first. meta.pagination counts bids. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ListBidsResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' post: operationId: placeBid summary: Place a bid description: |- Place a bid to buy a wine at your own price per unit. It rests on Cru for 90 days and fills when a seller accepts it. **To buy at the asking price, use an offer.** This places a resting bid. To buy an offer straight away at its price, POST /market/offers/{code}/buy. **The bid must fit your bidding allowance.** price × quantity above the account’s allowance is refused with TRADE_REFUSED, and its message gives both amounts. So is an untraded wine, or an account that cannot bid. tags: - Your bids x-cru-sdk: resource: bids method: place x-cru-scope: bids:write security: - ClientKey: [] ClientSecret: [] - OAuth: - bids:write requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PlaceBidRequest' x-cru-action: bid.place responses: '201': description: 'A partner credential gets 201 and the bid it placed. A connected app gets 202 and data.confirmation: nothing has happened yet.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Idempotent-Replayed: $ref: '#/components/headers/Idempotent-Replayed' content: application/json: schema: $ref: '#/components/schemas/PlaceBidResponse' '202': description: 'A connected app''s write is staged, not done: confirm it with POST /confirmations/{code} once the customer agrees.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/StagedResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /bids/{code}: get: operationId: getBid summary: Retrieve one of your bids description: One of your own bids by its code, with how much has matched, its status and expiry. Bids from other venues are not found here. tags: - Your bids x-cru-sdk: resource: bids method: get x-cru-scope: bids:read security: - ClientKey: [] ClientSecret: [] - OAuth: - bids:read parameters: - name: code in: path required: true description: The bid’s opaque code, from GET /bids or POST /bids. URL-encode it as a single path segment. schema: type: string responses: '200': description: Fields returned in data.bid. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/GetBidResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' patch: operationId: updateBid summary: Change a bid description: |- Change the price, quantity, local_only or auto_transfer of one of your live Cru bids. Any change, even to an option alone, runs it for 90 days from then. **What cannot be changed.** A partly matched bid, a bid that is no longer live, and a bid from another venue are refused with TRADE_REFUSED. So is a price above the cheapest offer, even when you change only an option: buy that offer instead. tags: - Your bids x-cru-sdk: resource: bids method: update x-cru-scope: bids:write security: - ClientKey: [] ClientSecret: [] - OAuth: - bids:write parameters: - name: code in: path required: true description: The bid’s opaque code, from GET /bids. URL-encode it as a single path segment. schema: type: string requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateBidRequest' x-cru-action: bid.update responses: '200': description: A partner credential gets 200 and the changed bid. A connected app gets 202 and a confirmation whose preview shows before and after, in your market’s currency. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Idempotent-Replayed: $ref: '#/components/headers/Idempotent-Replayed' content: application/json: schema: $ref: '#/components/schemas/UpdateBidResponse' '202': description: 'A connected app''s write is staged, not done: confirm it with POST /confirmations/{code} once the customer agrees.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/StagedResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' delete: operationId: cancelBid summary: Cancel a bid description: |- Cancel one of your live Cru bids by its code. A partner credential sends its reference in a JSON body. **A DELETE with a body.** A partner credential’s cancel must carry {"reference": "…"} as its JSON body. Check that your HTTP client sends a body on DELETE — not every client does by default. tags: - Your bids x-cru-sdk: resource: bids method: cancel x-cru-scope: bids:write security: - ClientKey: [] ClientSecret: [] - OAuth: - bids:write parameters: - name: code in: path required: true description: The bid’s opaque code, from GET /bids. URL-encode it as a single path segment. schema: type: string requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CancelBidRequest' x-cru-action: bid.cancel responses: '200': description: The cancelled bid, with status cancelled — or, for a connected app, a confirmation whose preview quotes the bid in your market’s currency. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Idempotent-Replayed: $ref: '#/components/headers/Idempotent-Replayed' content: application/json: schema: $ref: '#/components/schemas/CancelBidResponse' '202': description: 'A connected app''s write is staged, not done: confirm it with POST /confirmations/{code} once the customer agrees.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/StagedResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /bids/{code}/renew: post: operationId: renewBid summary: Renew a bid description: |- Put one of your bids back on the market for 90 days at the same price, quantity and currency: an expired or cancelled bid, or a live bid in its last 7 days. **To change the price as well, change the bid.** Renewing keeps the bid exactly as it was. To reprice a live bid, PATCH /bids/{code} instead: that also runs it for 90 days from the change. **Which bids can be renewed.** renewable on the bid says whether this endpoint takes it: an expired or cancelled bid, or a live one with 7 days or fewer left, with nothing matched. Others get TRADE_REFUSED — for a partly matched bid, place a new one for the rest. So, even if renewable, does a bid from another venue, an account that cannot bid, or a bid over your allowance on its site. tags: - Your bids x-cru-sdk: resource: bids method: renew x-cru-scope: bids:write security: - ClientKey: [] ClientSecret: [] - OAuth: - bids:write parameters: - name: code in: path required: true description: The bid’s opaque code, from GET /bids. URL-encode it as a single path segment. schema: type: string requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RenewBidRequest' x-cru-action: bid.renew responses: '200': description: The bid, live again until 90 days from today, and re-mirrored to Liv-ex if it was before. A connected app gets 202 and a confirmation whose preview quotes the bid in your market’s currency. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Idempotent-Replayed: $ref: '#/components/headers/Idempotent-Replayed' content: application/json: schema: $ref: '#/components/schemas/RenewBidResponse' '202': description: 'A connected app''s write is staged, not done: confirm it with POST /confirmations/{code} once the customer agrees.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/StagedResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /offers: get: operationId: listOffers summary: List your offers description: |- Your portfolio’s listed lines, by wine: what buyers pay and what you receive for each. **Your portfolio, listed lines only.** GET /offers answers as GET /portfolio?is_listed=true does: the same wines, lines and fields, and the same filters but is_listed, with the wines under data.offers rather than data.wines. A wine’s total_quantity is the units listed. **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. **offers:read shows what the wine cost.** GET /offers and GET /offers/{code} need offers:read, not portfolio:read, yet their lines carry everything GET /portfolio’s do, pricing.cost included: a credential that can read your listings sees what the listed wine cost you. tags: - Your offers x-cru-sdk: resource: offers method: list paged: true x-cru-scope: offers:read security: - ClientKey: [] ClientSecret: [] - OAuth: - offers:read parameters: - name: lwin in: query required: false description: 'Only these wines: up to 20 comma-separated 18-digit LWIN18 codes.' style: form explode: false schema: type: array items: type: string maxItems: 20 - name: wine_name in: query required: false description: '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. Anything else is refused with VALIDATION_INVALID_VALUE.' schema: type: string maxLength: 100 - name: current_location_code in: query required: false description: '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.' style: form explode: false schema: type: array items: type: string maxItems: 50 - name: deliverable_warehouse_code in: query required: false description: '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.' style: form explode: false schema: type: array items: type: string enum: - UK_DRAK - HK_KERRY - SG_TOLL - FR_DARTESS - US_NAPA - name: stock_type in: query required: false description: 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. style: form explode: false schema: type: array items: type: string enum: - cru - external - supplier - bpo - name: stock_status in: query required: false description: '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.' style: form explode: false schema: type: array items: type: string enum: - in_stock - in_transit - due_in - name: duty_paid in: query required: false description: 'true for only the portfolio lines whose duty is paid; false for only those whose duty is not. Omit it for both. Default: both.' schema: type: boolean - name: condition_status in: query required: false description: '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.' style: form explode: false schema: type: array items: type: string enum: - verified - client_reserves - apd - name: limit in: query required: false description: Number of wines to return. A larger value is refused with VALIDATION_INVALID_VALUE, not reduced. schema: type: integer minimum: 1 maximum: 250 default: 50 - name: offset in: query required: false description: Number of wines to skip. schema: type: integer minimum: 0 default: 0 responses: '200': description: 'data.offers, wines in name order, as GET /portfolio gives them with only their listed lines: each with its currency — the market’s, which every amount is in — and its lines under portfolio. meta.pagination counts wines.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ListOffersResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' post: operationId: createOffer summary: Create an offer description: |- List a line of your portfolio stored with Cru, wine you hold outside Cru, or your own stock as a supplier, for sale at a price per unit you choose. **Wine stored with Cru or held outside it, or a supplier’s own stock.** stock_type cru puts units of a line of your portfolio stored with Cru on sale. stock_type external lists wine in your own storage, for accounts Cru has set up to sell it. stock_type supplier adds an offer of your own stock, for a supplier whose offer feed Cru imports. To sell into a bid now, POST /market/bids/{code}/sell. **A line stored with Cru.** Its units go on sale at your price, and you receive it less Cru’s commission: the listed line’s pricing gives commission_percent, commission and net_proceeds. Listing moves them to a listed line with a portfolio_id of its own, not the one you sent, so take the answer’s for PATCH and DELETE /offers/{code}. A line already listed is refused: change its price or quantity with PATCH /offers/{code} instead. Removing the offer later only takes it off sale. **Your next offer feed import replaces a supplier offer.** An offer listed with stock_type supplier joins your offers on Cru only until your next offer feed import to Cru, which replaces it, as it replaces all your offers: your feed stays the source of truth. To keep selling the wine, put it in your feed too. **A supplier offer.** It is sold from your own warehouse, so it takes no warehouse_code, and it must be priced in your offer feed’s currency: on a Cru site that quotes in another, it is refused with TRADE_REFUSED, and the message names the currency. Its line comes back with stock_type supplier, and your price as both pricing.listing_price and pricing.net_proceeds. You can change it afterwards with PATCH /offers/{code}, like any of your supplier offers. **Removing wine held outside Cru takes it out of your portfolio.** Listing wine held outside Cru creates its units in your Cru portfolio, in bond. Removing the offer later deletes them again. tags: - Your offers x-cru-sdk: resource: offers method: create x-cru-scope: offers:write security: - ClientKey: [] ClientSecret: [] - OAuth: - offers:write requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateOfferRequest' x-cru-action: offer.list responses: '201': description: A partner credential gets 201 and the wine, with the line just listed. A connected app gets 202 and a confirmation. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Idempotent-Replayed: $ref: '#/components/headers/Idempotent-Replayed' content: application/json: schema: $ref: '#/components/schemas/CreateOfferResponse' '202': description: 'A connected app''s write is staged, not done: confirm it with POST /confirmations/{code} once the customer agrees.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/StagedResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /offers/{code}: get: operationId: getOffer summary: Retrieve one of your offers description: |- One listed line of your portfolio, by its portfolio_id: its wine as GET /offers gives it, with that line alone. **One item of GET /offers.** data.offer is what GET /offers gives as one item of data.offers: the same wine and fields, with only the line whose portfolio_id you gave under portfolio, and total_quantity its units. A listing’s code gives the wine with all the listing’s lines. **offers:read shows what the wine cost.** GET /offers and GET /offers/{code} need offers:read, not portfolio:read, yet their lines carry everything GET /portfolio’s do, pricing.cost included: a credential that can read your listings sees what the listed wine cost you. tags: - Your offers x-cru-sdk: resource: offers method: get x-cru-scope: offers:read security: - ClientKey: [] ClientSecret: [] - OAuth: - offers:read parameters: - name: code in: path required: true description: A listed line’s portfolio_id, from GET /offers, GET /portfolio or the offer a write answered with, to read just that line’s units. A listing’s LISTING- code also works, for the whole listing. URL-encode it as a single path segment. schema: type: string responses: '200': description: data.offer, one wine as GET /offers gives it, with its currency — the market’s, which every amount is in — and the line or lines asked for under portfolio. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/GetOfferResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' patch: operationId: updateOffer summary: Change an offer description: |- Change the asking price or quantity of one listed line of your portfolio, or of a whole listing. A repriced line comes back with a new portfolio_id. **What a change does depends on where the wine is.** Held outside Cru (external): a lower quantity deletes units, a higher one creates them. Stored with Cru: units come off or go on sale, up to what you hold in that warehouse. Supplier offers take a lasting override. BPO stock cannot be changed. **Change one line, or a whole listing.** Given a listed line’s portfolio_id, only that line’s units change: the preview’s before and after quantities are the line’s, and its code the listing’s. A lower quantity takes units off that line alone. Repriced, the line gets a new portfolio_id, which the offer in the answer carries. Given a listing’s code, every line of the listing changes. tags: - Your offers x-cru-sdk: resource: offers method: update x-cru-scope: offers:write security: - ClientKey: [] ClientSecret: [] - OAuth: - offers:write parameters: - name: code in: path required: true description: A listed line’s portfolio_id, from GET /offers, GET /portfolio or the offer a write answered with, to act on just that line’s units. A listing’s LISTING- code also works, for the whole listing. URL-encode it as a single path segment. schema: type: string requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateOfferRequest' x-cru-action: offer.update responses: '200': description: The wine as it now is, with only the lines the changed units are on — under a new portfolio_id if the price changed. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Idempotent-Replayed: $ref: '#/components/headers/Idempotent-Replayed' content: application/json: schema: $ref: '#/components/schemas/UpdateOfferResponse' '202': description: 'A connected app''s write is staged, not done: confirm it with POST /confirmations/{code} once the customer agrees.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/StagedResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' delete: operationId: removeOffer summary: Remove an offer description: |- Take one listed line of your portfolio, or a whole listing, off sale. Wine stored with Cru stays in your portfolio; wine held outside Cru is removed from it. **A DELETE with a body.** A partner credential sends {"reference": "…"} as the JSON body. Supplier offers cannot be removed here — they are switched off on the Cru website — and BPO stock cannot be taken off sale. **Remove one line, or a whole listing.** Given a listed line’s portfolio_id, only that line’s units come off sale, and the preview’s offer has that line alone. Given a listing’s code, every line of the listing comes off sale. **Back in your portfolio, under another portfolio_id.** Wine stored with Cru stays in your portfolio, no longer listed, so the answer’s offer has its line under another portfolio_id than the one you sent, with is_listed false. That line can hold more units than came off sale, when you hold others of the same kind that are not listed. Send its portfolio_id to POST /offers with stock_type cru to list them again. Wine held outside Cru is deleted, so offer is null. tags: - Your offers x-cru-sdk: resource: offers method: remove x-cru-scope: offers:write security: - ClientKey: [] ClientSecret: [] - OAuth: - offers:write parameters: - name: code in: path required: true description: A listed line’s portfolio_id, from GET /offers, GET /portfolio or the offer a write answered with, to act on just that line’s units. A listing’s LISTING- code also works, for the whole listing. URL-encode it as a single path segment. schema: type: string requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RemoveOfferRequest' x-cru-action: offer.remove responses: '200': description: 'Your portfolio after the removal: the wine as GET /portfolio gives it now, with the lines the units taken off sale are on, or null once they are deleted.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Idempotent-Replayed: $ref: '#/components/headers/Idempotent-Replayed' content: application/json: schema: $ref: '#/components/schemas/RemoveOfferResponse' '202': description: 'A connected app''s write is staged, not done: confirm it with POST /confirmations/{code} once the customer agrees.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/StagedResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /portfolio: get: operationId: listPortfolio summary: Retrieve your portfolio description: |- 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. **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 or can 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 always 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. tags: - Your portfolio x-cru-sdk: resource: portfolio method: list paged: true x-cru-scope: portfolio:read security: - ClientKey: [] ClientSecret: [] - OAuth: - portfolio:read parameters: - name: lwin in: query required: false description: 'Only these wines: up to 20 comma-separated 18-digit LWIN18 codes.' style: form explode: false schema: type: array items: type: string maxItems: 20 - name: wine_name in: query required: false description: '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. Anything else is refused with VALIDATION_INVALID_VALUE.' schema: type: string maxLength: 100 - name: current_location_code in: query required: false description: '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.' style: form explode: false schema: type: array items: type: string maxItems: 50 - name: deliverable_warehouse_code in: query required: false description: '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.' style: form explode: false schema: type: array items: type: string enum: - UK_DRAK - HK_KERRY - SG_TOLL - FR_DARTESS - US_NAPA - name: stock_type in: query required: false description: 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. style: form explode: false schema: type: array items: type: string enum: - cru - external - supplier - bpo - name: stock_status in: query required: false description: '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.' style: form explode: false schema: type: array items: type: string enum: - in_stock - in_transit - due_in - name: duty_paid in: query required: false description: 'true for only the portfolio lines whose duty is paid; false for only those whose duty is not. Omit it for both. Default: both.' schema: type: boolean - name: condition_status in: query required: false description: '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.' style: form explode: false schema: type: array items: type: string enum: - verified - client_reserves - apd - name: is_listed in: query required: false description: '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.' schema: type: boolean - name: limit in: query required: false description: Number of wines to return. A larger value is refused with VALIDATION_INVALID_VALUE, not reduced. schema: type: integer minimum: 1 maximum: 100 default: 50 - name: offset in: query required: false description: Number of wines to skip. schema: type: integer minimum: 0 default: 0 - name: include_market_price in: query required: false deprecated: true description: Accepted and ignored, for callers written before it became the default. schema: type: boolean responses: '200': description: 'data.wines, in name order, 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.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ListPortfolioResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /trades/purchases: get: operationId: listPurchases summary: List your purchases description: |- What you have bought on Cru, by order line, newest first, with each order’s status, invoice and units. **The order and invoice links are for the customer.** order_url and invoice_url are pages on the Cru site the order was placed on, for the customer signed in there: an API key or access token does not open them. Show them to the customer rather than fetching them. tags: - Your portfolio x-cru-sdk: resource: trades method: list_purchases paged: true x-cru-scope: trades:read security: - ClientKey: [] ClientSecret: [] - OAuth: - trades:read parameters: - name: lwin in: query required: false description: 'Only these wines: up to 20 comma-separated 18-digit LWIN18 codes.' style: form explode: false schema: type: array items: type: string maxItems: 20 - name: status in: query required: false description: 'Only order lines with a unit in any of these states, comma-separated, in any case: in_portfolio, for_sale, sold, in_transit or delivered, as units[].status gives them. A line with no units stored with Cru matches none. Anything else is refused with VALIDATION_UNSUPPORTED_VALUE.' style: form explode: false schema: type: array items: type: string enum: - in_portfolio - for_sale - sold - in_transit - delivered - name: sort in: query required: false description: 'What to order by: traded_at, the date of the order, the only choice.' schema: type: string enum: - traded_at default: traded_at - name: direction in: query required: false description: desc for newest first, or asc for oldest first. schema: type: string enum: - desc - asc default: desc - name: limit in: query required: false description: Number of purchases to return. A larger value is refused with VALIDATION_INVALID_VALUE, not reduced. schema: type: integer minimum: 1 maximum: 250 default: 50 - name: offset in: query required: false description: Number of purchases to skip. schema: type: integer minimum: 0 default: 0 responses: '200': description: data.purchases, newest first unless direction is asc. price and total are in each purchase’s own currency. meta.pagination counts order lines. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ListPurchasesResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /trades/sales: get: operationId: listSales summary: List your sales description: |- What you have sold on Cru, one unit at a time, newest first: commission, what you received and profit. **One sale per unit.** Each unit sold is its own sale, with quantity 1, its cru_id and no order number. sold_price, commission and settlement_fee take the sale down to net_proceeds, what you received, and profit_loss sets that against cost. **Wine held outside Cru, on its way to Cru.** Once it sells, wine held outside Cru goes to the Cru warehouse deliver_to names, by deliver_by. status says how far it has got: transfer_needed until a transfer to Cru is booked, then awaiting_transfer, with transfer_ref naming the transfer; on_purchase_order while it is due in on a purchase order; and delivered_to_cru once it is there. Wine stored with Cru has no deliver_to, and is always delivered_to_cru. tags: - Your portfolio x-cru-sdk: resource: trades method: list_sales paged: true x-cru-scope: trades:read security: - ClientKey: [] ClientSecret: [] - OAuth: - trades:read parameters: - name: lwin in: query required: false description: 'Only these wines: up to 20 comma-separated 18-digit LWIN18 codes.' style: form explode: false schema: type: array items: type: string maxItems: 20 - name: status in: query required: false description: 'Only sales in any of these states, comma-separated, in any case: transfer_needed, awaiting_transfer, on_purchase_order or delivered_to_cru. Anything else is refused with VALIDATION_UNSUPPORTED_VALUE.' style: form explode: false schema: type: array items: type: string enum: - transfer_needed - awaiting_transfer - on_purchase_order - delivered_to_cru - name: deliverable_warehouse_code in: query required: false description: 'Only sales of wine held outside Cru going to any of these Cru warehouses, comma-separated: UK_DRAK, HK_KERRY, SG_TOLL, FR_DARTESS, US_NAPA. Wine stored with Cru matches none. An unknown code is refused with VALIDATION_INVALID_VALUE.' style: form explode: false schema: type: array items: type: string enum: - UK_DRAK - HK_KERRY - SG_TOLL - FR_DARTESS - US_NAPA - name: sort in: query required: false description: 'What to order by: traded_at, the date of the sale, the only choice.' schema: type: string enum: - traded_at default: traded_at - name: direction in: query required: false description: desc for newest first, or asc for oldest first. schema: type: string enum: - desc - asc default: desc - name: limit in: query required: false description: Number of sales to return. A larger value is refused with VALIDATION_INVALID_VALUE, not reduced. schema: type: integer minimum: 1 maximum: 250 default: 50 - name: offset in: query required: false description: Number of sales to skip. schema: type: integer minimum: 0 default: 0 responses: '200': description: data.sales, newest first unless direction is asc. Every amount is in the market’s currency. meta.pagination counts sales. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ListSalesResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /market/offers/{code}/buy: post: operationId: buyMarketOffer summary: Buy an offer description: |- Buy one offer on Cru’s market now, at its asking price, paid from your Cru account credit or on invoice and kept in your Cru storage. **The offer you name, and bids:write as well.** There is no “buy at the lowest offer”: pick one from GET /market/wines/{lwin18}/offers. The purchase needs bids:write besides orders:write. To sell into a bid instead, POST /market/bids/{code}/sell. **A partner key should send max_price.** A partner’s purchase has no preview, so max_price is what holds the price you read from the book. If the offer costs more, nothing is bought. **Paid from credit or on invoice, never by card.** It goes through the Cru website’s own Buy now, paid from your Cru account credit, or on invoice if your account has invoice terms. The wine is kept in your Cru storage. If neither covers the total, nothing is bought, and the message says how much credit is missing. tags: - Buy and sell x-cru-sdk: resource: market method: buy_offer x-cru-scope: orders:write security: - ClientKey: [] ClientSecret: [] - OAuth: - orders:write parameters: - name: code in: path required: true description: The offer’s opaque code, from GET /market/offers. URL-encode it as a single path segment. schema: type: string requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BuyMarketOfferRequest' x-cru-action: bid.buy responses: '201': description: The order placed. A connected app gets 202 and a confirmation whose preview quotes the purchase and how it is paid. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Idempotent-Replayed: $ref: '#/components/headers/Idempotent-Replayed' content: application/json: schema: $ref: '#/components/schemas/BuyMarketOfferResponse' '202': description: 'A connected app''s write is staged, not done: confirm it with POST /confirmations/{code} once the customer agrees.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/StagedResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /market/bids/{code}/sell: post: operationId: sellToMarketBid summary: Sell into a bid description: |- Sell into one bid on Cru’s market now, at its price after commission, credited to your Cru account: a line of your portfolio, or new stock. **The bid you name, and offers:write as well.** There is no “sell at the best bid”: pick one from GET /market/wines/{lwin18}/bids by its requirements. The sale needs offers:write besides orders:write. To buy an offer instead, POST /market/offers/{code}/buy. **A partner key should send min_price.** A partner’s sale has no preview, so min_price is what holds the price you read from the book. If the bid pays less, nothing is sold. **Wine held outside Cru, not in your portfolio yet.** For accounts Cru has set up to sell it, as the website’s Sell Now does: send stock_type external and warehouse_code, with no portfolio_id, and Cru creates the units at that warehouse and fills the bid with them at once — or deletes them again, and sells nothing, if the fill fails. You set no price: you receive the bid’s price less that warehouse’s settlement fee — its settlement_fee in GET /warehouses, such as GBP 6.00 per unit at UK_DRAK — and a corporate account pays none. Selling confirms the wine is free from material faults, in its original packaging, in a professional warehouse and not duty paid, and that you will transfer it to that warehouse; Cru emails you the purchase order. A bid that takes landed stock only cannot be filled this way. **Your own stock, as a supplier.** A supplier whose offer feed Cru imports can sell stock that is not in its feed: send stock_type supplier, with no portfolio_id. Cru adds an offer of just that quantity to your feed, at the feed’s warehouse, verified and not duty paid, and fills the bid with it at once, so selling it all leaves nothing on sale. If it cannot fill the bid, or the fill fails, it is taken back and nothing is sold. Supplier stock, new or a line of your portfolio, fills only bids placed on Cru. tags: - Buy and sell x-cru-sdk: resource: market method: sell_to_bid x-cru-scope: orders:write security: - ClientKey: [] ClientSecret: [] - OAuth: - orders:write parameters: - name: code in: path required: true description: The bid’s opaque code, from GET /market/bids. URL-encode it as a single path segment. schema: type: string requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SellToMarketBidRequest' x-cru-action: offer.sell responses: '200': description: What was sold, and from what. A connected app gets 202 and a confirmation whose preview quotes the sale. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Idempotent-Replayed: $ref: '#/components/headers/Idempotent-Replayed' content: application/json: schema: $ref: '#/components/schemas/SellToMarketBidResponse' '202': description: 'A connected app''s write is staged, not done: confirm it with POST /confirmations/{code} once the customer agrees.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/StagedResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /addresses/inbond: get: operationId: listInbondAddresses summary: List your inbond addresses description: |- The inbond addresses on your account: each an inbond warehouse, with your bond account number, site code and nickname there. **Only inbond addresses.** Not your other addresses or payment details. A connected app gets addresses:read only by asking for it by name: an app that asks for nothing in particular does not. tags: - Your addresses x-cru-sdk: resource: inbond_addresses method: list x-cru-scope: addresses:read security: - ClientKey: [] ClientSecret: [] - OAuth: - addresses:read responses: '200': description: data.inbond_addresses is an array, oldest first. Each is the warehouse as GET /warehouses/inbond serves it now, then your account there. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ListInbondAddressesResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' post: operationId: addInbondAddress summary: Add an inbond address description: |- Save an inbond address on your account: an inbond warehouse from GET /warehouses/inbond, and your bond account number there. **Never your default address.** It is saved as the Cru website’s address form saves one with “In bond” ticked, at the warehouse’s own address, and is never made your default. A warehouse Cru does not list has to be added by Cru first: suggest it with POST /warehouses/inbond if Cru has granted you warehouses:suggest, or the customer emails customerservice@cruworldwine.com. tags: - Your addresses x-cru-sdk: resource: inbond_addresses method: add x-cru-scope: addresses:write security: - ClientKey: [] ClientSecret: [] - OAuth: - addresses:write requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AddInbondAddressRequest' x-cru-action: inbond_address.add responses: '201': description: A partner credential gets 201 and the address saved. A connected app gets 202 and a confirmation. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Idempotent-Replayed: $ref: '#/components/headers/Idempotent-Replayed' content: application/json: schema: $ref: '#/components/schemas/AddInbondAddressResponse' '202': description: 'A connected app''s write is staged, not done: confirm it with POST /confirmations/{code} once the customer agrees.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/StagedResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /addresses/inbond/{id}: delete: operationId: removeInbondAddress summary: Remove an inbond address description: |- Remove an inbond address from your account: the one you added last at an inbond warehouse, by its inbond_address_id from GET /addresses/inbond. **Never your default address.** Your default billing or delivery address on Cru is not removed: choose another default on the Cru website first. Your other addresses are never changed. **A DELETE with a body.** A partner credential sends {"reference": "…"} as the JSON body. tags: - Your addresses x-cru-sdk: resource: inbond_addresses method: remove x-cru-scope: addresses:write security: - ClientKey: [] ClientSecret: [] - OAuth: - addresses:write parameters: - name: id in: path required: true description: The inbond_address_id of the address’s warehouse, from GET /addresses/inbond. With more than one address of yours there, the one added last is removed. schema: type: integer requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RemoveInbondAddressRequest' x-cru-action: inbond_address.remove responses: '200': description: A partner credential gets 200 and the address removed. A connected app gets 202 and a confirmation. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Idempotent-Replayed: $ref: '#/components/headers/Idempotent-Replayed' content: application/json: schema: $ref: '#/components/schemas/RemoveInbondAddressResponse' '202': description: 'A connected app''s write is staged, not done: confirm it with POST /confirmations/{code} once the customer agrees.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/StagedResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /confirmations/{code}: get: operationId: getConfirmation summary: Retrieve a confirmation description: |- See what a confirmation code stands for and how far it has got: pending, executing, completed, failed, expired or cancelled. **Connected apps only.** Confirmations belong to the app that staged them. A partner credential never has one, and gets CONFIRMATION_NOT_FOUND. tags: - Confirmations x-cru-sdk: resource: confirmations method: get security: - OAuth: [] parameters: - name: code in: path required: true description: The cnf_ code a connected app’s write returned. URL-encode it as a single path segment. schema: type: string responses: '200': description: Fields returned in data. Reading a pending code past its expiry marks it expired. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/GetConfirmationResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' post: operationId: confirmInstruction summary: Confirm an instruction description: |- Carry out an instruction a connected app staged. Only the same app, for the same customer and market, can confirm it. **Only after the customer says yes.** This is the call that trades with the customer’s money or wine. Show them preview.summary and confirm only on their explicit yes. tags: - Confirmations x-cru-sdk: resource: confirmations method: confirm security: - OAuth: [] parameters: - name: code in: path required: true description: The cnf_ code a connected app’s write returned. URL-encode it as a single path segment. schema: type: string responses: '200': description: 'The action’s own result: 201 for bid.place, offer.list, bid.buy and inbond_address.add, 200 for the rest. A repeat replays it with Idempotent-Replayed: true.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Idempotent-Replayed: $ref: '#/components/headers/Idempotent-Replayed' content: application/json: schema: $ref: '#/components/schemas/ConfirmInstructionResponse' '201': description: 'The action’s own result: 201 for bid.place, offer.list, bid.buy and inbond_address.add, 200 for the rest. A repeat replays it with Idempotent-Replayed: true.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Idempotent-Replayed: $ref: '#/components/headers/Idempotent-Replayed' content: application/json: schema: $ref: '#/components/schemas/ConfirmInstructionResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' delete: operationId: cancelConfirmation summary: Discard an instruction description: Withdraw a pending instruction before it is confirmed. It answers 204 with no body, and the code cannot be used again. tags: - Confirmations x-cru-sdk: resource: confirmations method: cancel security: - OAuth: [] parameters: - name: code in: path required: true description: The cnf_ code a connected app’s write returned. URL-encode it as a single path segment. schema: type: string responses: '204': description: Cancelled. No body. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' components: securitySchemes: ClientKey: type: apiKey in: header name: CLIENT-KEY description: A partner credential's key. Always sent with CLIENT-SECRET. ClientSecret: type: apiKey in: header name: CLIENT-SECRET description: A partner credential's secret, shown once when it is issued. OAuth: type: oauth2 description: 'A connected app acting for a Cru customer: authorization code with PKCE (S256), then refresh tokens. Its writes are staged for confirmation. The endpoints are on each market''s host; the UK''s are shown.' flows: authorizationCode: authorizationUrl: https://uk.cruworldwine.com/api/oauth/authorize tokenUrl: https://uk.cruworldwine.com/api/oauth/token refreshUrl: https://uk.cruworldwine.com/api/oauth/token scopes: meta:read: Check the connection, and read Cru’s warehouses and the inbond warehouses market:read: Read Cru’s bid and offer books, and the bids and offers on each wine wines:read: Look up wine reference data portfolio:read: Read your portfolio bids:read: Read your own bids offers:read: Read your own listings, with what the listed wine cost trades:read: Read what you have bought and sold, with the order and invoice references addresses:read: Read your own inbond addresses bids:write: Place, change, renew and cancel bids offers:write: List, change and remove offers orders:write: Buy and sell straight away, alongside bids:write or offers:write addresses:write: Save and remove inbond addresses headers: X-Request-Id: description: 'The id this request is traced by. Send your own (8-64 of A-Z a-z 0-9 . _ : -) to have it used.' schema: type: string Idempotent-Replayed: description: true when this is the stored answer to an earlier request with the same reference, not a new action. schema: type: string enum: - 'true' responses: BadRequest: description: 'The request could not be understood: VALIDATION_UNKNOWN_PARAMETER, VALIDATION_MALFORMED_BODY.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' Unauthorized: description: 'Authentication failed: AUTH_INVALID_CREDENTIALS.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' Forbidden: description: 'Not permitted: AUTH_CLIENT_SUSPENDED, AUTH_INSUFFICIENT_SCOPE, AUTH_IP_NOT_ALLOWED, AUTH_HTTPS_REQUIRED, AUTH_STORE_NOT_ALLOWED, AUTH_ACCOUNT_ON_HOLD.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' NotFound: description: 'Not found: NOT_FOUND, BID_NOT_FOUND, OFFER_NOT_FOUND, CONFIRMATION_NOT_FOUND, API_VERSION_UNSUPPORTED.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' MethodNotAllowed: description: 'Method not allowed: METHOD_NOT_ALLOWED.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' Allow: description: The methods the URL takes. schema: type: string content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' Conflict: description: 'Conflict: REQUEST_IN_PROGRESS, PRICE_CHANGED, CONFIRMATION_LIMIT_REACHED.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' Gone: description: 'Gone: CONFIRMATION_EXPIRED.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' UnprocessableEntity: description: 'Validation failed: VALIDATION_REQUIRED_FIELD, VALIDATION_INVALID_VALUE, VALIDATION_UNSUPPORTED_VALUE, TRADE_REFUSED.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' TooManyRequests: description: 'Too many requests: RATE_LIMIT_EXCEEDED.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' InternalError: description: 'Unexpected error: INTERNAL_ERROR.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' ServiceUnavailable: description: 'Temporarily unavailable: SERVICE_UNAVAILABLE.' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' schemas: AddInbondAddressRequest: type: object required: - inbond_address_id - account_number properties: reference: description: 'Your idempotency key: letters and digits, then . _ : or - allowed. Required on a partner credential’s write and kept for good, so a retry with it can never act twice. Ignored for connected apps.' type: string minLength: 1 maxLength: 50 pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$ x-cru-required-for: partner inbond_address_id: description: 'A bonded warehouse from GET /warehouses/inbond: not one of the duty-paid ones, whose is_bonded is false.' type: integer minimum: 1 account_number: description: Your bond account number at that warehouse. type: string maxLength: 50 site_code: description: Your site code or sub-account there, if the warehouse uses one. type: string maxLength: 50 nickname: description: Your own name for the address. type: string maxLength: 50 additionalProperties: false AddInbondAddressResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/InbondAddressResult' ApiClient: type: object required: - environment - key_prefix - organisation - label - market - currency - scopes - expires_at properties: environment: description: live on production, test everywhere else. type: string key_prefix: description: The start of the client key that called, such as cru_live_ABCD... Null for a connected app. type: string nullable: true organisation: description: The account the credential acts for. type: string nullable: true label: description: The credential’s label, or the connected app’s registered name. type: string nullable: true market: description: The market you called, such as uk. type: string x-extensible-enum: - uk - us - hk - sg - eu - ae - cn - fr currency: description: ISO 4217 currency prices are quoted in on this market. type: string x-extensible-enum: - GBP - USD - HKD - SGD - EUR - AED - CNY scopes: description: The scopes granted. type: array items: type: string expires_at: description: When the credential expires, or null if it does not. For a connected app, when the access token expires. type: string format: date-time nullable: true BidRequirements: type: object required: - condition_status - landed_stock_only - deliverable_warehouses properties: condition_status: description: 'The lowest condition the bid accepts: verified, client_reserves or apd.' type: string x-extensible-enum: - verified - client_reserves - apd landed_stock_only: description: Whether only stock that has already landed can fill it. type: boolean deliverable_warehouses: description: 'The Cru warehouses stock can be in, or be delivered to, to fill it: the codes GET /warehouses lists.' type: array items: type: string BidResult: type: object description: 'A bid write''s result: the bid as GET /bids/{code} returns it now.' required: - action - status - bid properties: action: description: The action that ran. type: string x-extensible-enum: - bid.place - bid.update - bid.cancel - bid.renew - bid.buy - offer.list - offer.update - offer.remove - offer.sell - inbond_address.add - inbond_address.remove - inbond_warehouse.suggest status: description: completed. type: string x-extensible-enum: - completed bid: $ref: '#/components/schemas/OwnBid' BuyMarketOfferRequest: type: object required: - quantity properties: reference: description: 'Your idempotency key: letters and digits, then . _ : or - allowed. Required on a partner credential’s write and kept for good, so a retry with it can never act twice. Ignored for connected apps.' type: string minLength: 1 maxLength: 50 pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$ x-cru-required-for: partner quantity: description: 'Units to buy: at least the offer’s min_quantity, and no more than it has.' type: integer minimum: 1 maximum: 1000 max_price: description: The highest price per unit you will pay, in the market’s currency — price as GET /market/offers shows it — to at most 2 decimal places. type: number minimum: 0 exclusiveMinimum: true additionalProperties: false BuyMarketOfferResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/BuyResult' BuyResult: type: object description: The result of buying an offer. required: - action - status - order - lwin18 - quantity - price properties: action: description: The action that ran. type: string x-extensible-enum: - bid.place - bid.update - bid.cancel - bid.renew - bid.buy - offer.list - offer.update - offer.remove - offer.sell - inbond_address.add - inbond_address.remove - inbond_warehouse.suggest status: description: completed. type: string x-extensible-enum: - completed order: $ref: '#/components/schemas/Order' lwin18: description: The wine. type: string quantity: description: Units bought. type: integer price: description: Per unit. type: number CancelBidRequest: type: object properties: reference: description: 'Your idempotency key: letters and digits, then . _ : or - allowed. Required on a partner credential’s write and kept for good, so a retry with it can never act twice. Ignored for connected apps.' type: string minLength: 1 maxLength: 50 pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$ x-cru-required-for: partner additionalProperties: false CancelBidResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/BidResult' ConfirmInstructionResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/InstructionResult' Confirmation: type: object required: - action - status - preview - expires_at properties: action: description: The action staged. type: string x-extensible-enum: - bid.place - bid.update - bid.cancel - bid.renew - bid.buy - offer.list - offer.update - offer.remove - offer.sell - inbond_address.add - inbond_address.remove - inbond_warehouse.suggest status: description: pending, executing, completed, failed, expired or cancelled. type: string x-extensible-enum: - pending - executing - completed - failed - expired - cancelled preview: $ref: '#/components/schemas/Preview' expires_at: description: RFC 3339 UTC. type: string format: date-time nullable: true result: description: 'What the instruction did: the same payload confirming it returned. Present once completed.' type: object additionalProperties: true error: description: code and message of the refusal. Present once failed. type: object required: - code - message properties: code: type: string x-extensible-enum: - VALIDATION_UNKNOWN_PARAMETER - VALIDATION_MALFORMED_BODY - VALIDATION_REQUIRED_FIELD - VALIDATION_INVALID_VALUE - VALIDATION_UNSUPPORTED_VALUE - AUTH_INVALID_CREDENTIALS - AUTH_CLIENT_SUSPENDED - AUTH_INSUFFICIENT_SCOPE - AUTH_IP_NOT_ALLOWED - AUTH_HTTPS_REQUIRED - AUTH_STORE_NOT_ALLOWED - AUTH_ACCOUNT_ON_HOLD - NOT_FOUND - BID_NOT_FOUND - OFFER_NOT_FOUND - CONFIRMATION_NOT_FOUND - METHOD_NOT_ALLOWED - API_VERSION_UNSUPPORTED - REQUEST_IN_PROGRESS - PRICE_CHANGED - CONFIRMATION_LIMIT_REACHED - CONFIRMATION_EXPIRED - TRADE_REFUSED - RATE_LIMIT_EXCEEDED - INTERNAL_ERROR - SERVICE_UNAVAILABLE message: type: string nullable: true CreateOfferRequest: type: object required: - stock_type - quantity - price properties: reference: description: 'Your idempotency key: letters and digits, then . _ : or - allowed. Required on a partner credential’s write and kept for good, so a retry with it can never act twice. Ignored for connected apps.' type: string minLength: 1 maxLength: 50 pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$ x-cru-required-for: partner stock_type: description: 'What you are listing: cru, a line of your portfolio stored with Cru; external, wine you hold outside Cru; or supplier, your own stock as a supplier whose offer feed Cru imports. The fields below that say which of them they are for are refused for the others, with VALIDATION_UNKNOWN_PARAMETER. Anything else, bpo included, is refused with VALIDATION_INVALID_VALUE: BPO stock cannot be listed through the API.' type: string enum: - cru - external - supplier portfolio_id: description: 'The line to list, from GET /portfolio: one with stock_type cru that is not listed yet (is_listed false). Its units go on sale as a listed line with a portfolio_id of its own, which the answer gives. Only with stock_type cru.' type: string x-cru-when: stock_type: - cru x-cru-required-when: true lwin18: description: The wine. Cru must trade it. Only with stock_type external or supplier. type: string pattern: ^[0-9]{18}$ x-cru-when: stock_type: - external - supplier x-cru-required-when: true quantity: description: Units to list. For cru, at most the line’s quantity. type: integer minimum: 1 maximum: 1000 price: description: 'Price per unit in the market’s currency, to at most 2 decimal places. For cru and external, the asking price, what the buyer pays: the line’s pricing.listing_price. For supplier, what you receive: buyers pay Cru’s price, and the line gives yours as both pricing.listing_price and pricing.net_proceeds.' type: number minimum: 0 exclusiveMinimum: true warehouse_code: description: 'The Cru warehouse it is sold through: one GET /warehouses marks sells_your_inbond_wine for you. The line gives it back as warehouse.deliverable_warehouse_code. Only with stock_type external.' type: string x-cru-when: stock_type: - external x-cru-required-when: true condition_status: description: verified (Verified), client_reserves (Client Reserve) or apd (As per description). For external, it defaults to, and cannot exceed, the level Cru set for your account. For supplier, it defaults to verified, or to apd when duty_paid is true, which takes nothing else. Only with stock_type external or supplier. type: string enum: - verified - client_reserves - apd x-cru-when: stock_type: - external - supplier condition_text: description: What buyers are told about the condition. Required for apd, and refused for verified; client_reserves may have it. Duty-paid stock says “Duty Paid in the UK” unless you give it. Only with stock_type supplier. type: string maxLength: 200 x-cru-when: stock_type: - supplier duty_paid: description: true when the duty has been paid, which makes the offer apd. Defaults to false, in bond. Only with stock_type supplier. type: boolean x-cru-when: stock_type: - supplier cost: description: What you paid per unit, for your records. Only with stock_type external. type: number minimum: 0 exclusiveMinimum: true x-cru-when: stock_type: - external inbond_address_id: description: 'The inbond warehouse the wine is in now, from GET /warehouses/inbond. Leave it out if you are not sure where the wine is: Cru records it as not sure, as the website’s “Not Sure” option does. Only with stock_type external.' type: integer minimum: 1 x-cru-when: stock_type: - external additionalProperties: false CreateOfferResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/OfferResult' ErrorEntry: type: object required: - code - message properties: code: description: A stable, symbolic code such as AUTH_INSUFFICIENT_SCOPE. Branch on this. type: string x-extensible-enum: - VALIDATION_UNKNOWN_PARAMETER - VALIDATION_MALFORMED_BODY - VALIDATION_REQUIRED_FIELD - VALIDATION_INVALID_VALUE - VALIDATION_UNSUPPORTED_VALUE - AUTH_INVALID_CREDENTIALS - AUTH_CLIENT_SUSPENDED - AUTH_INSUFFICIENT_SCOPE - AUTH_IP_NOT_ALLOWED - AUTH_HTTPS_REQUIRED - AUTH_STORE_NOT_ALLOWED - AUTH_ACCOUNT_ON_HOLD - NOT_FOUND - BID_NOT_FOUND - OFFER_NOT_FOUND - CONFIRMATION_NOT_FOUND - METHOD_NOT_ALLOWED - API_VERSION_UNSUPPORTED - REQUEST_IN_PROGRESS - PRICE_CHANGED - CONFIRMATION_LIMIT_REACHED - CONFIRMATION_EXPIRED - TRADE_REFUSED - RATE_LIMIT_EXCEEDED - INTERNAL_ERROR - SERVICE_UNAVAILABLE message: description: What went wrong. For TRADE_REFUSED and PRICE_CHANGED it is the reason, worded so it can be shown to a customer. type: string field: description: The query parameter or body field the problem is about. type: string details: type: object additionalProperties: true description: 'Structured context: required_scope, store and allowed_stores, allowed_methods, retry_after.' ErrorResponse: type: object required: - status - message - meta - data - errors properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - ERROR message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: description: Always null on an error. nullable: true type: object errors: description: One entry per problem. type: array minItems: 1 items: $ref: '#/components/schemas/ErrorEntry' GetBidResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - bid properties: bid: $ref: '#/components/schemas/OwnBid' GetConfirmationResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - confirmation properties: confirmation: $ref: '#/components/schemas/Confirmation' GetInbondWarehouseResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - inbond_warehouse properties: inbond_warehouse: $ref: '#/components/schemas/InbondWarehouse' GetMarketBidResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - bid properties: bid: $ref: '#/components/schemas/MarketBidDetail' GetMarketOfferResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - offer properties: offer: $ref: '#/components/schemas/MarketOfferDetail' GetMarketWineBidsResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - market properties: market: $ref: '#/components/schemas/MarketWine' GetMarketWineOffersResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - market properties: market: $ref: '#/components/schemas/MarketWine' GetMarketWineResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - market properties: market: $ref: '#/components/schemas/MarketWine' GetOfferResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - offer properties: offer: $ref: '#/components/schemas/PortfolioWine' GetWarehouseResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - warehouse properties: warehouse: $ref: '#/components/schemas/Warehouse' GetWineResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - wine properties: wine: $ref: '#/components/schemas/WineDetail' InbondAddress: type: object required: - inbond_address_id - name - company - street - city - region - postcode - country - telephone - lcb_site_code - is_bonded - account_number - site_code - nickname - pending properties: inbond_address_id: description: The inbond warehouse, as GET /warehouses/inbond lists it. type: integer name: description: The warehouse’s name, such as Seckfords. type: string company: description: The company that runs it. type: string nullable: true street: description: Its street address, both lines joined with ", ". type: string nullable: true city: description: Its town or city. type: string nullable: true region: description: Its county, state or region. type: string nullable: true postcode: description: Its postcode. type: string nullable: true country: description: An ISO country code, such as GB. type: string nullable: true telephone: description: Its phone number. type: string nullable: true lcb_site_code: description: Its London City Bond site code, such as MM for LCB Melksham. Null for most. type: string nullable: true is_bonded: description: Whether it is bonded. A few are duty-paid storage, which cannot be an inbond address. type: boolean account_number: description: Your bond account number at that warehouse. type: string nullable: true site_code: description: Your own site code or sub-account there, where the warehouse uses one. Not its lcb_site_code. type: string nullable: true nickname: description: Your own name for the address. type: string nullable: true pending: description: True while Cru has not approved a warehouse you suggested. type: boolean InbondAddressResult: type: object description: An inbond address write's result. required: - action - status - inbond_address properties: action: description: The action that ran. type: string x-extensible-enum: - bid.place - bid.update - bid.cancel - bid.renew - bid.buy - offer.list - offer.update - offer.remove - offer.sell - inbond_address.add - inbond_address.remove - inbond_warehouse.suggest status: description: completed. type: string x-extensible-enum: - completed inbond_address: $ref: '#/components/schemas/InbondAddress' InbondWarehouse: type: object required: - inbond_address_id - name - company - street - city - region - postcode - country - telephone - lcb_site_code - is_bonded - pending properties: inbond_address_id: description: What POST /offers and POST /market/bids/{code}/sell take to say where the wine is now, and POST /addresses/inbond to save an address there. Never a warehouse_code. type: integer name: description: The warehouse’s name, such as Seckfords. type: string company: description: The company that runs it. type: string nullable: true street: description: Its street address, both lines joined with ", ". type: string nullable: true city: description: Its town or city. type: string nullable: true region: description: Its county, state or region. type: string nullable: true postcode: description: Its postcode. type: string nullable: true country: description: An ISO country code, such as GB. type: string nullable: true telephone: description: Its phone number. type: string nullable: true lcb_site_code: description: Its London City Bond site code, such as MM for LCB Melksham. Null for most. type: string nullable: true is_bonded: description: Whether it is bonded. A few are duty-paid storage, which cannot be an inbond address. type: boolean pending: description: 'True for one you suggested that Cru has not approved yet: only you see it, and only you can use its inbond_address_id.' type: boolean InbondWarehouseResult: type: object description: The inbond warehouse suggested, pending until Cru reviews it. required: - action - status - inbond_warehouse properties: action: description: The action that ran. type: string x-extensible-enum: - bid.place - bid.update - bid.cancel - bid.renew - bid.buy - offer.list - offer.update - offer.remove - offer.sell - inbond_address.add - inbond_address.remove - inbond_warehouse.suggest status: description: completed. type: string x-extensible-enum: - completed inbond_warehouse: $ref: '#/components/schemas/InbondWarehouse' InstructionResult: type: object description: 'What a confirmed instruction did: the same result the write would have answered a partner with, which depends on the action - BidResult, OfferResult, OfferRemoveResult, BuyResult, SellResult or InbondAddressResult.' required: - action - status properties: action: type: string x-extensible-enum: - bid.place - bid.update - bid.cancel - bid.renew - bid.buy - offer.list - offer.update - offer.remove - offer.sell - inbond_address.add - inbond_address.remove - inbond_warehouse.suggest status: type: string x-extensible-enum: - completed additionalProperties: true LastTrade: type: object required: - price - traded_at properties: price: description: The last traded price, in the market's currency. type: number traded_at: description: When it traded, RFC 3339 UTC. type: string format: date-time LinePricing: type: object required: - cost - listing_price - commission_percent - commission - settlement_fee - net_proceeds properties: cost: description: What you paid per unit. Null for a supplier’s own stock, and when it cannot be converted. type: number nullable: true listing_price: description: '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.' type: number nullable: true commission_percent: description: '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.' type: number nullable: true commission: description: '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.' type: number nullable: true settlement_fee: description: 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. type: number nullable: true net_proceeds: description: 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. type: number nullable: true LineWarehouse: type: object required: - location_type - current_location - current_location_code - deliverable_warehouse_code properties: location_type: description: '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.' type: string nullable: true x-extensible-enum: - cru - inbond - address - supplier current_location: description: '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.' type: string nullable: true current_location_code: description: '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.' type: string nullable: true deliverable_warehouse_code: description: '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 always have one, which for stock at the supplier’s own warehouse is the Cru warehouse in its country. 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.' type: string nullable: true ListBidsResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - bids properties: bids: type: array items: $ref: '#/components/schemas/OwnBid' ListInbondAddressesResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - inbond_addresses properties: inbond_addresses: type: array items: $ref: '#/components/schemas/InbondAddress' ListInbondWarehousesResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - inbond_warehouses properties: inbond_warehouses: type: array items: $ref: '#/components/schemas/InbondWarehouse' ListMarketBidsResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - markets properties: markets: type: array items: $ref: '#/components/schemas/MarketWine' ListMarketOffersResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - markets properties: markets: type: array items: $ref: '#/components/schemas/MarketWine' ListMarketResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - markets properties: markets: type: array items: $ref: '#/components/schemas/MarketWine' ListOffersResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - offers properties: offers: type: array items: $ref: '#/components/schemas/PortfolioWine' ListPortfolioResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - wines properties: wines: type: array items: $ref: '#/components/schemas/PortfolioWine' ListPurchasesResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - purchases properties: purchases: type: array items: $ref: '#/components/schemas/Purchase' ListSalesResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - sales properties: sales: type: array items: $ref: '#/components/schemas/Sale' ListWarehousesResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - warehouses properties: warehouses: type: array items: $ref: '#/components/schemas/Warehouse' MarketBid: type: object required: - code - price - quantity - is_own_bid - expires_at - updated_at - requirements properties: code: description: 'Opaque bid code: BID- and 43 more characters. Do not parse it. Your own bids carry the same code here and in /bids.' type: string price: description: Net price per unit — what a seller receives after Cru’s commission — converted into the market’s currency, to 2 decimal places. type: number quantity: description: Units the bid still wants. type: integer is_own_bid: description: True when the bid is yours. Your own bids are listed, but you cannot sell into one. type: boolean expires_at: description: YYYY-MM-DD. For bids Cru carries from other venues this is always set two days ahead, not taken from the venue. type: string format: date nullable: true updated_at: description: Last change, RFC 3339 UTC. type: string format: date-time nullable: true requirements: $ref: '#/components/schemas/BidRequirements' MarketBidDetail: type: object required: - lwin18 - wine_name - vintage - pack_size - product_url - currency - code - price - quantity - is_own_bid - expires_at - updated_at - requirements properties: lwin18: description: 'The 18-digit LWIN: wine, vintage and pack together. Match on all 18 digits.' type: string wine_name: description: Cru’s name for the wine. type: string nullable: true vintage: description: The vintage year. 1000 means non-vintage. type: integer nullable: true pack_size: description: Pack format, for example 6x75cl. type: string nullable: true product_url: description: The wine’s page on the Cru storefront for the market you called. type: string format: uri nullable: true currency: description: 'ISO 4217 currency of every price in this market: the currency of the market you called.' type: string x-extensible-enum: - GBP - USD - HKD - SGD - EUR - AED - CNY code: description: 'Opaque bid code: BID- and 43 more characters. Do not parse it. Your own bids carry the same code here and in /bids.' type: string price: description: Net price per unit — what a seller receives after Cru’s commission — converted into the market’s currency, to 2 decimal places. type: number quantity: description: Units the bid still wants. type: integer is_own_bid: description: True when the bid is yours. Your own bids are listed, but you cannot sell into one. type: boolean expires_at: description: YYYY-MM-DD. For bids Cru carries from other venues this is always set two days ahead, not taken from the venue. type: string format: date nullable: true updated_at: description: Last change, RFC 3339 UTC. type: string format: date-time nullable: true requirements: $ref: '#/components/schemas/BidRequirements' MarketOffer: type: object required: - code - price - quantity - min_quantity - status - eta - duty_paid - condition_status - condition_text - photo_urls - warehouse_code properties: code: description: 'Opaque offer code: OFFER- and 43 more characters. Do not parse it.' type: string price: description: Gross price per unit — what a buyer pays — in the market’s currency. type: number quantity: description: Units on offer at this price. type: integer min_quantity: description: The fewest units that can be bought from this offer — almost always 1. A smaller purchase is refused. type: integer status: description: in_stock, in_transit or due_in, as the Cru product page shows it. Offers from other sellers and venues are always due_in, except a customer’s own stock already in Cru storage, which is in_stock. type: string x-extensible-enum: - in_stock - in_transit - due_in eta: description: 'YYYY-MM-DD: when the wine is expected in warehouse_code, the warehouse it is sold from and where a purchase is kept. Today for in_stock. Null until Cru’s market index has dated the offer.' type: string format: date nullable: true duty_paid: description: Whether duty has been paid on the wine. type: boolean condition_status: description: verified (Verified), client_reserves (Client Reserve) or apd (As per description), strongest first. API conventions explains each. type: string nullable: true x-extensible-enum: - verified - client_reserves - apd condition_text: description: The written condition of As per description and Client Reserve stock, or null. Liv-ex and supplier offers never have one. type: string nullable: true photo_urls: description: Photos of the wine, [] when there are none. Cru’s own stock links to Cru’s media; other photos are served by GET /photos/{id}. type: array items: type: string format: uri warehouse_code: description: The Cru warehouse the wine is in — UK_DRAK, HK_KERRY, SG_TOLL, FR_DARTESS, US_NAPA — or for wine held elsewhere the one in its country. Null where Cru has none there. type: string nullable: true MarketOfferDetail: type: object required: - lwin18 - wine_name - vintage - pack_size - product_url - currency - code - price - quantity - min_quantity - status - eta - duty_paid - condition_status - condition_text - photo_urls - warehouse_code properties: lwin18: description: 'The 18-digit LWIN: wine, vintage and pack together. Match on all 18 digits.' type: string wine_name: description: Cru’s name for the wine. type: string nullable: true vintage: description: The vintage year. 1000 means non-vintage. type: integer nullable: true pack_size: description: Pack format, for example 6x75cl. type: string nullable: true product_url: description: The wine’s page on the Cru storefront for the market you called. type: string format: uri nullable: true currency: description: 'ISO 4217 currency of every price in this market: the currency of the market you called.' type: string x-extensible-enum: - GBP - USD - HKD - SGD - EUR - AED - CNY code: description: 'Opaque offer code: OFFER- and 43 more characters. Do not parse it.' type: string price: description: Gross price per unit — what a buyer pays — in the market’s currency. type: number quantity: description: Units on offer at this price. type: integer min_quantity: description: The fewest units that can be bought from this offer — almost always 1. A smaller purchase is refused. type: integer status: description: in_stock, in_transit or due_in, as the Cru product page shows it. Offers from other sellers and venues are always due_in, except a customer’s own stock already in Cru storage, which is in_stock. type: string x-extensible-enum: - in_stock - in_transit - due_in eta: description: 'YYYY-MM-DD: when the wine is expected in warehouse_code, the warehouse it is sold from and where a purchase is kept. Today for in_stock. Null until Cru’s market index has dated the offer.' type: string format: date nullable: true duty_paid: description: Whether duty has been paid on the wine. type: boolean condition_status: description: verified (Verified), client_reserves (Client Reserve) or apd (As per description), strongest first. API conventions explains each. type: string nullable: true x-extensible-enum: - verified - client_reserves - apd condition_text: description: The written condition of As per description and Client Reserve stock, or null. Liv-ex and supplier offers never have one. type: string nullable: true photo_urls: description: Photos of the wine, [] when there are none. Cru’s own stock links to Cru’s media; other photos are served by GET /photos/{id}. type: array items: type: string format: uri warehouse_code: description: The Cru warehouse the wine is in — UK_DRAK, HK_KERRY, SG_TOLL, FR_DARTESS, US_NAPA — or for wine held elsewhere the one in its country. Null where Cru has none there. type: string nullable: true MarketWine: type: object required: - lwin18 - wine_name - vintage - pack_size - product_url - currency properties: lwin18: description: 'The 18-digit LWIN: wine, vintage and pack together. Match on all 18 digits.' type: string wine_name: description: Cru’s name for the wine. type: string nullable: true vintage: description: The vintage year. 1000 means non-vintage. type: integer nullable: true pack_size: description: Pack format, for example 6x75cl. type: string nullable: true product_url: description: The wine’s page on the Cru storefront for the market you called. type: string format: uri nullable: true currency: description: 'ISO 4217 currency of every price in this market: the currency of the market you called.' type: string x-extensible-enum: - GBP - USD - HKD - SGD - EUR - AED - CNY bids: description: 'Cru''s bids on the wine, in book order: Cru''s own first, then by price. Present on /market, /market/bids and the wine''s bids.' type: array items: $ref: '#/components/schemas/MarketBid' market_price: description: 'Only with include_market_price=true: Cru’s market price, in currency. Null when Cru has no price for the wine.' type: number nullable: true last_trade: description: 'Only with include_last_trade=true: price, and traded_at. Null when there is none.' nullable: true allOf: - $ref: '#/components/schemas/LastTrade' offers: description: The offers of the wine, cheapest first. Present on /market, /market/offers and the wine's offers. type: array items: $ref: '#/components/schemas/MarketOffer' Meta: type: object required: - version - timestamp - request_id properties: version: description: The envelope's contract version, 1.0. It moves when the envelope gains a field, not with the route. type: string timestamp: description: When the response was made, RFC 3339 UTC. type: string format: date-time request_id: description: The id this request is traced by, also sent as the X-Request-Id header. Quote it to Cru support. type: string pagination: $ref: '#/components/schemas/Pagination' OfferRemoveResult: type: object description: The result of taking an offer off sale. required: - action - status - offer - removed - deleted properties: action: description: The action that ran. type: string x-extensible-enum: - bid.place - bid.update - bid.cancel - bid.renew - bid.buy - offer.list - offer.update - offer.remove - offer.sell - inbond_address.add - inbond_address.remove - inbond_warehouse.suggest status: description: completed. type: string x-extensible-enum: - completed offer: description: 'The wine as GET /portfolio gives it now, with only the lines the units taken off sale are on: no longer listed, so under another portfolio_id. Null for wine held outside Cru, whose units are deleted.' nullable: true allOf: - $ref: '#/components/schemas/PortfolioWine' removed: description: Units taken off sale. type: integer deleted: description: True when the units were held outside Cru (external), and so left the portfolio. type: boolean OfferResult: type: object description: An offer write's result. required: - action - status - offer properties: action: description: The action that ran. type: string x-extensible-enum: - bid.place - bid.update - bid.cancel - bid.renew - bid.buy - offer.list - offer.update - offer.remove - offer.sell - inbond_address.add - inbond_address.remove - inbond_warehouse.suggest status: description: completed. type: string x-extensible-enum: - completed offer: description: The wine as GET /offers/{code} gives it, with only the lines the units written are on now. nullable: true allOf: - $ref: '#/components/schemas/PortfolioWine' Order: type: object required: - number - status - total - currency - pending_payment properties: number: description: The Cru order number. type: string status: description: The order's status, or null when it could not be loaded yet. type: string nullable: true total: description: What the order costs, account credit included. type: number currency: description: The order's currency. type: string x-extensible-enum: - GBP - USD - HKD - SGD - EUR - AED - CNY pending_payment: description: True when a card payment still needs the customer (3-D Secure) before the order is paid. type: boolean OwnBid: type: object required: - code - client_ref - lwin18 - wine_name - vintage - pack_size - product_url - price - currency - bid_currency - quantity - quantity_matched - quantity_open - order_numbers - order_urls - status - renewable - market - local_only - auto_transfer - expires_on - created_at - updated_at properties: code: description: Opaque bid code, the same one /market/bids shows for this bid. type: string client_ref: description: Your own reference, if you gave one when placing the bid. type: string nullable: true lwin18: description: 'The 18-digit LWIN: wine, vintage and pack together. Match on all 18 digits.' type: string wine_name: description: Cru’s name for the wine. type: string nullable: true vintage: description: The vintage year. 1000 means non-vintage. type: integer nullable: true pack_size: description: Pack format, for example 6x75cl. type: string nullable: true product_url: description: The wine’s page on the Cru storefront for the market you called. type: string format: uri nullable: true price: description: Gross price per unit you offered — before Cru’s commission — in the currency of the market you called. A bid placed in another currency is converted at today’s rate, as My Bids on Cru shows it. type: number currency: description: The currency of the market you called, the same for every bid, so one listing never mixes currencies. type: string x-extensible-enum: - GBP - USD - HKD - SGD - EUR - AED - CNY bid_currency: description: The currency the bid was placed in, which its price was converted from. type: string x-extensible-enum: - GBP - USD - HKD - SGD - EUR - AED - CNY quantity: description: Total units bid for. type: integer quantity_matched: description: Units matched so far. type: integer quantity_open: description: 'Units still open: quantity less quantity_matched while live, otherwise 0.' type: integer order_numbers: description: The Cru sales order numbers the bid matched into, oldest first. [] if none. type: array items: type: string order_urls: description: Each order’s page on Cru Markets, in the same order as order_numbers, on the site the bid was placed on (its market), not the one you called. type: array items: type: string format: uri status: description: live, matched (awaiting invoice), complete, cancelled, expired or error. A live bid past its expiry reports expired. type: string x-extensible-enum: - live - matched - complete - cancelled - expired - error renewable: description: Whether POST /bids/{code}/renew takes the bid now. Your allowance is checked only on renewal. type: boolean market: description: The Cru site the bid was placed on, such as uk or hk. type: string nullable: true x-extensible-enum: - uk - us - hk - sg - eu - ae - cn - fr local_only: description: Accepts only stock already on that site. type: boolean auto_transfer: description: Moves the wine into your storage on that site when the bid fills. type: boolean expires_on: description: YYYY-MM-DD. type: string format: date nullable: true created_at: description: RFC 3339 UTC. type: string format: date-time nullable: true updated_at: description: RFC 3339 UTC. type: string format: date-time nullable: true Pagination: type: object required: - limit - offset properties: limit: description: The limit applied. type: integer offset: description: The offset applied. type: integer total: description: How many there are in all. Absent where counting is not worth it (GET /wines). type: integer has_more: description: 'Whether offset + limit is short of total: page on while it is true.' type: boolean Ping: type: object required: - pong - client properties: pong: description: Always true on success. type: boolean client: description: The credential, or the connected app, the request was made with. $ref: '#/components/schemas/ApiClient' PingResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/Ping' PlaceBidRequest: type: object required: - lwin18 - quantity - price properties: reference: description: 'Your idempotency key: letters and digits, then . _ : or - allowed. Required on a partner credential’s write and kept for good, so a retry with it can never act twice. Ignored for connected apps.' type: string minLength: 1 maxLength: 50 pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$ x-cru-required-for: partner lwin18: description: The wine. Cru must trade it. type: string pattern: ^[0-9]{18}$ quantity: description: Units, in the LWIN18’s pack size. type: integer minimum: 1 maximum: 1000 price: description: 'Gross price per unit you will pay, in the market’s currency, to at most 2 decimal places: 30780 or 30780.50.' type: number minimum: 0 exclusiveMinimum: true local_only: description: Accept only stock already on this Cru site. Default false. type: boolean auto_transfer: description: Move the wine into your storage on this site when the bid fills. Default false. type: boolean client_ref: description: 'Your own label for the bid — letters, digits, spaces and . / # : _ - — shown on it and filterable in GET /bids. Unique among all your bids, ignoring case. Not an idempotency key.' type: string maxLength: 50 additionalProperties: false PlaceBidResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/BidResult' PortfolioLine: type: object required: - portfolio_id - stock_type - stock_status - duty_paid - condition_status - condition_text - is_listed - pricing - photo_urls - quantity - warehouse properties: portfolio_id: description: '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.' type: string stock_type: description: '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.' type: string x-extensible-enum: - cru - external - supplier - bpo stock_status: description: '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.' type: string x-extensible-enum: - in_stock - in_transit - due_in duty_paid: description: Whether duty has been paid. type: boolean condition_status: description: 'The units’ condition status: verified (Verified), client_reserves (Client Reserve) or apd (As per description).' type: string nullable: true x-extensible-enum: - verified - client_reserves - apd condition_text: description: The written description of the units’ condition. Null when there is none. type: string nullable: true is_listed: description: Whether the units are listed for sale. Always true on GET /offers and GET /offers/{code}, and for a supplier’s own stock. type: boolean pricing: $ref: '#/components/schemas/LinePricing' photo_urls: description: Photos of the units in this line, on Cru’s media. [] when there are none. type: array items: type: string format: uri quantity: description: Units in this line. type: integer warehouse: $ref: '#/components/schemas/LineWarehouse' PortfolioWine: type: object required: - lwin18 - wine_name - vintage - pack_size - product_url - currency - total_quantity - market_price - lowest_offer_price - highest_bid_price - portfolio properties: lwin18: description: 'The 18-digit LWIN: wine, vintage and pack together. Match on all 18 digits.' type: string wine_name: description: Cru’s name for the wine. type: string nullable: true vintage: description: The vintage year. 1000 means non-vintage. type: integer nullable: true pack_size: description: Pack format, for example 6x75cl. type: string nullable: true product_url: description: The wine’s page on the Cru storefront for the market you called. type: string format: uri nullable: true currency: description: '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.' type: string x-extensible-enum: - GBP - USD - HKD - SGD - EUR - AED - CNY total_quantity: description: '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.' type: integer market_price: description: Cru’s market price for this wine, in its currency. Null when Cru has no price. type: number nullable: true lowest_offer_price: description: 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. type: number nullable: true highest_bid_price: description: '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.' type: number nullable: true portfolio: description: Lines of identical units, described below. type: array items: $ref: '#/components/schemas/PortfolioLine' Preview: type: object description: 'What the customer is asked to confirm: summary, one sentence they can say yes to, and the action''s own fields, which differ by action.' required: - summary properties: summary: type: string description: One sentence the customer can say yes to. additionalProperties: true Purchase: type: object required: - lwin18 - wine_name - vintage - pack_size - quantity - price - total - currency - reference - traded_at - order_status - order_url - invoice_number - invoice_url - units properties: lwin18: description: 'The 18-digit LWIN: wine, vintage and pack together. Match on all 18 digits.' type: string wine_name: description: Cru’s name for the wine. type: string nullable: true vintage: description: The vintage year. 1000 means non-vintage. type: integer nullable: true pack_size: description: Pack format, for example 6x75cl. type: string nullable: true quantity: description: Units in this order line, less any cancelled or refunded. type: integer price: description: What you paid per unit. type: number total: description: price × quantity. type: number currency: description: 'The order’s currency, which price and total are in as they were paid: never converted.' type: string x-extensible-enum: - GBP - USD - HKD - SGD - EUR - AED - CNY reference: description: The Cru order number, which each line of the order shows. A purchase has no id of its own. type: string traded_at: description: When the order was placed, RFC 3339 UTC. type: string format: date-time order_status: description: The order’s status, as Cru’s site labels it, such as “Paid and Processing”. type: string nullable: true order_url: description: The order’s page on Cru Markets, on the site it was placed on. It opens for the customer signed in to Cru, not with an API key or token. type: string format: uri invoice_number: description: The order’s first invoice. null until the order is invoiced. type: string nullable: true invoice_url: description: That invoice as a PDF, on the Cru site the order was placed on. Like order_url, it opens only for the customer signed in to Cru. null until the order is invoiced. type: string format: uri nullable: true units: description: Each unit of this line stored with Cru, one per bottle or case, lowest cru_id first. [] when none of it is. type: array items: $ref: '#/components/schemas/PurchaseUnit' PurchaseUnit: type: object required: - cru_id - warehouse_ref - deliverable_warehouse_code - condition_status - status properties: cru_id: description: The unit’s Cru ID. type: integer nullable: true warehouse_ref: description: 'Its reference at the warehouse: the Warehouse ID on Cru’s site.' type: string nullable: true deliverable_warehouse_code: description: 'The Cru warehouse it is in: UK_DRAK, HK_KERRY, SG_TOLL, FR_DARTESS, US_NAPA.' type: string nullable: true condition_status: description: 'The unit’s condition status: verified (Verified), client_reserves (Client Reserve) or apd (As per description).' type: string nullable: true x-extensible-enum: - verified - client_reserves - apd status: description: 'Where it is now, as the status filter takes it: in_portfolio, still in your portfolio and not listed; for_sale, listed; sold; in_transit; or delivered, taken out of Cru’s storage.' type: string x-extensible-enum: - in_portfolio - for_sale - sold - in_transit - delivered RemoveInbondAddressRequest: type: object properties: reference: description: 'Your idempotency key: letters and digits, then . _ : or - allowed. Required on a partner credential’s write and kept for good, so a retry with it can never act twice. Ignored for connected apps.' type: string minLength: 1 maxLength: 50 pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$ x-cru-required-for: partner additionalProperties: false RemoveInbondAddressResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/InbondAddressResult' RemoveOfferRequest: type: object properties: reference: description: 'Your idempotency key: letters and digits, then . _ : or - allowed. Required on a partner credential’s write and kept for good, so a retry with it can never act twice. Ignored for connected apps.' type: string minLength: 1 maxLength: 50 pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$ x-cru-required-for: partner additionalProperties: false RemoveOfferResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/OfferRemoveResult' RenewBidRequest: type: object properties: reference: description: 'Your idempotency key: letters and digits, then . _ : or - allowed. Required on a partner credential’s write and kept for good, so a retry with it can never act twice. Ignored for connected apps.' type: string minLength: 1 maxLength: 50 pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$ x-cru-required-for: partner additionalProperties: false RenewBidResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/BidResult' Sale: type: object required: - lwin18 - wine_name - vintage - pack_size - quantity - price - total - currency - reference - traded_at - cru_id - transfer_ref - cost - sold_price - commission_percent - commission - settlement_fee - net_proceeds - profit_loss - profit_loss_percent - deliver_to - deliverable_warehouse_code - deliver_by - status properties: lwin18: description: 'The 18-digit LWIN: wine, vintage and pack together. Match on all 18 digits.' type: string wine_name: description: Cru’s name for the wine. type: string nullable: true vintage: description: The vintage year. 1000 means non-vintage. type: integer nullable: true pack_size: description: Pack format, for example 6x75cl. type: string nullable: true quantity: description: 'Always 1: each unit sold is its own sale.' type: integer price: description: 'What the unit sold for, the Sold list’s Sold For. For wine held outside Cru, that is after Cru’s commission: sold_price less commission. For wine stored with Cru it is usually sold_price, but can differ, such as when the unit sold into a bid at another price.' type: number nullable: true total: description: The same as price, for one unit. type: number nullable: true currency: description: 'The market’s. Every amount on a sale is in it: one bought or sold in another currency is converted at the rate of that day.' type: string x-extensible-enum: - GBP - USD - HKD - SGD - EUR - AED - CNY reference: description: 'Always null: a sale has no order number.' nullable: true type: string traded_at: description: When it sold, RFC 3339 UTC. type: string format: date-time nullable: true cru_id: description: The unit’s Cru ID. type: integer nullable: true transfer_ref: description: The transfer that brings it to Cru, such as SM00004417, once one is booked. type: string nullable: true cost: description: What you paid for it. null when no cost is recorded. type: number nullable: true sold_price: description: The price Cru’s commission was worked out from, before the commission and any settlement_fee. For wine stored with Cru, its listing price, fixed on the unit when it was listed. type: number nullable: true commission_percent: description: Cru’s commission, as a percentage of sold_price. 0.0 for a supplier. type: number commission: description: Cru’s commission, as an amount. type: number nullable: true settlement_fee: description: The warehouse’s fee, for wine held outside Cru. 0.0 for wine stored with Cru. type: number nullable: true net_proceeds: description: 'What you received, the Sold list’s You Received: sold_price less commission and settlement_fee.' type: number nullable: true profit_loss: description: net_proceeds less cost. null when cost is. type: number nullable: true profit_loss_percent: description: profit_loss as a percentage of cost, to one decimal place. null when no cost is recorded. type: number nullable: true deliver_to: description: For wine held outside Cru, the name of the Cru warehouse it goes to. null for wine stored with Cru. type: string nullable: true deliverable_warehouse_code: description: 'That warehouse’s code: UK_DRAK, HK_KERRY, SG_TOLL, FR_DARTESS, US_NAPA. null for wine stored with Cru.' type: string nullable: true deliver_by: description: 'For wine held outside Cru, when it is due there, YYYY-MM-DD: its transfer’s expected date or, without one, two weeks after it sold. null for wine stored with Cru.' type: string format: date nullable: true status: description: 'Where the wine is in reaching Cru, as the status filter takes it: transfer_needed, awaiting_transfer, on_purchase_order or delivered_to_cru. Wine stored with Cru is always delivered_to_cru.' type: string nullable: true x-extensible-enum: - transfer_needed - awaiting_transfer - on_purchase_order - delivered_to_cru SearchWinesResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: type: object required: - wines - currency properties: wines: type: array items: $ref: '#/components/schemas/Wine' currency: type: string description: The currency every price is in. SellResult: type: object description: The result of selling into a bid. required: - action - status - sold - requested - bid_code - stock_type - portfolio_id - lwin18 - price - total - currency properties: action: description: The action that ran. type: string x-extensible-enum: - bid.place - bid.update - bid.cancel - bid.renew - bid.buy - offer.list - offer.update - offer.remove - offer.sell - inbond_address.add - inbond_address.remove - inbond_warehouse.suggest status: description: completed. type: string x-extensible-enum: - completed sold: description: 'Units sold: can be fewer than requested.' type: integer requested: description: The quantity you sent. type: integer bid_code: description: The bid sold into. type: string stock_type: description: What was sold, as you sent it. type: string x-extensible-enum: - cru - external - supplier - bpo portfolio_id: description: The line sold from, as you sent it; null for new stock. type: string nullable: true lwin18: description: The wine. type: string price: description: Per unit, after commission, and after the settlement fee for wine held outside Cru. type: number total: description: Credited to your Cru account. type: number currency: description: The market’s currency. type: string x-extensible-enum: - GBP - USD - HKD - SGD - EUR - AED - CNY SellToMarketBidRequest: type: object required: - stock_type - quantity properties: reference: description: 'Your idempotency key: letters and digits, then . _ : or - allowed. Required on a partner credential’s write and kept for good, so a retry with it can never act twice. Ignored for connected apps.' type: string minLength: 1 maxLength: 50 pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$ x-cru-required-for: partner stock_type: description: 'What you are selling: cru, wine stored with Cru; external, wine you hold outside Cru; or supplier, your own stock as a supplier whose offer feed Cru imports. Anything else, bpo included, is refused with VALIDATION_INVALID_VALUE: BPO stock cannot be sold through the API.' type: string enum: - cru - external - supplier portfolio_id: description: 'A line of your portfolio, from GET /portfolio or GET /offers, of this bid’s wine and of the stock_type you send: its units are sold, and only those. Required for cru, as wine stored with Cru is always sold from your portfolio. Wine held outside Cru fills a bid only while its line is listed, as on the Cru website. Leave it out to sell new external or supplier stock.' type: string quantity: description: 'Units to sell: with portfolio_id, at most what the line has that the bid can take.' type: integer minimum: 1 maximum: 1000 min_price: description: The lowest price per unit you will take, after Cru’s commission, in the market’s currency — price as GET /market/bids shows it, less the settlement fee for wine held outside Cru — to at most 2 decimal places. type: number minimum: 0 exclusiveMinimum: true warehouse_code: description: 'New stock only, and needed for it: the Cru warehouse wine you hold outside Cru, not in your portfolio yet, is delivered to — one of the bid’s deliverable_warehouses that GET /warehouses marks sells_your_inbond_wine for you. Only with stock_type external.' type: string x-cru-when: stock_type: - external condition_status: description: 'New external or supplier stock only: verified, the one condition that can fill a bid, and the default.' type: string enum: - verified - client_reserves - apd cost: description: 'New stock only: what you paid per unit, in the market’s currency. Only with stock_type external.' type: number minimum: 0 exclusiveMinimum: true x-cru-when: stock_type: - external inbond_address_id: description: 'New stock only: the inbond warehouse the wine is in now, from GET /warehouses/inbond. Leave it out if you are not sure where the wine is: Cru records it as not sure, as the website’s Sell Now does. Only with stock_type external.' type: integer minimum: 1 x-cru-when: stock_type: - external additionalProperties: false SellToMarketBidResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/SellResult' Staged: type: object required: - confirmation properties: confirmation: $ref: '#/components/schemas/StagedConfirmation' StagedConfirmation: type: object required: - code - action - status - expires_at - preview properties: code: description: 'cnf_ and 43 more characters. A secret: the only handle on the instruction, valid for 15 minutes, once.' type: string pattern: ^cnf_ action: description: The action staged, such as bid.place. type: string x-extensible-enum: - bid.place - bid.update - bid.cancel - bid.renew - bid.buy - offer.list - offer.update - offer.remove - offer.sell - inbond_address.add - inbond_address.remove - inbond_warehouse.suggest status: description: pending. type: string x-extensible-enum: - pending expires_at: description: RFC 3339 UTC. type: string format: date-time preview: $ref: '#/components/schemas/Preview' StagedResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/Staged' SuggestInbondWarehouseRequest: type: object required: - name - country properties: reference: description: 'Your idempotency key: letters and digits, then . _ : or - allowed. Required on a partner credential’s write and kept for good, so a retry with it can never act twice. Ignored for connected apps.' type: string minLength: 1 maxLength: 50 pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$ x-cru-required-for: partner name: description: The warehouse’s name. type: string maxLength: 100 country: description: Its ISO country code, such as GB or FR. type: string pattern: ^[A-Za-z]{2}$ city: description: Its town or city. type: string maxLength: 100 street: description: Its street address. type: string maxLength: 150 region: description: Its county, state or region. type: string maxLength: 100 postcode: description: Its postcode. type: string maxLength: 20 telephone: description: Its phone number. type: string maxLength: 30 is_bonded: description: 'Whether it is a bonded warehouse: true unless you send false. Only a bonded one can be an inbond address.' type: boolean additionalProperties: false SuggestInbondWarehouseResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/InbondWarehouseResult' UpdateBidRequest: type: object properties: reference: description: 'Your idempotency key: letters and digits, then . _ : or - allowed. Required on a partner credential’s write and kept for good, so a retry with it can never act twice. Ignored for connected apps.' type: string minLength: 1 maxLength: 50 pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$ x-cru-required-for: partner price: description: New gross price per unit, in your market’s currency, as GET /bids quotes it. The bid moves into that currency, as an edit on Cru does, so its bid_currency becomes your market’s. type: number minimum: 0 exclusiveMinimum: true quantity: description: New quantity. A quantity alone keeps the price GET /bids quotes. type: integer minimum: 1 maximum: 1000 local_only: description: Accept only stock already on this Cru site. Omit to keep it. type: boolean auto_transfer: description: Move the wine into your storage on this site when the bid fills. Omit to keep it. type: boolean additionalProperties: false UpdateBidResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/BidResult' UpdateOfferRequest: type: object properties: reference: description: 'Your idempotency key: letters and digits, then . _ : or - allowed. Required on a partner credential’s write and kept for good, so a retry with it can never act twice. Ignored for connected apps.' type: string minLength: 1 maxLength: 50 pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$ x-cru-required-for: partner price: description: 'New price per unit, in the market’s currency, as GET /offers and GET /portfolio quote it: pricing.listing_price. A supplier offer’s is converted into your offer feed’s currency.' type: number minimum: 0 exclusiveMinimum: true quantity: description: New quantity. Send price, quantity or both. type: integer minimum: 1 maximum: 1000 additionalProperties: false UpdateOfferResponse: type: object required: - status - message - meta - data properties: status: description: OK on success, ERROR on failure. It describes the call, never a resource. type: string enum: - OK message: description: 'A sentence for people. It is not stable: never branch on it.' type: string meta: $ref: '#/components/schemas/Meta' data: $ref: '#/components/schemas/OfferResult' Warehouse: type: object required: - code - name - market - address - phone - bond_references - delivery_instructions - sells_your_inbond_wine - settlement_fee - currency properties: code: description: UK_DRAK, HK_KERRY, SG_TOLL, FR_DARTESS, US_NAPA. type: string name: description: The warehouse’s short name. type: string market: description: The Cru site the warehouse belongs to, such as uk. type: string nullable: true x-extensible-enum: - uk - us - hk - sg - eu - ae - cn - fr address: description: street, city, region, postcode and country (an ISO country code), each nullable. type: object required: - street - city - region - postcode - country properties: street: description: Street lines, comma-separated. type: string nullable: true city: description: City. type: string nullable: true region: description: Region or county, when there is one. nullable: true type: string postcode: description: Postcode. type: string nullable: true country: description: ISO 3166-1 alpha-2 country code. type: string nullable: true phone: description: Contact number. type: string nullable: true bond_references: description: Excise and bond references to quote when delivering in bond. type: array items: type: string delivery_instructions: description: Plain text, with line breaks as \n. type: string nullable: true sells_your_inbond_wine: description: 'Whether wine you hold outside Cru can be sold through it: the warehouse_code values POST /offers and POST /market/bids/{code}/sell accept from you. False on every row for an account not set up for it.' type: boolean settlement_fee: description: 'Taken from each unit of that wine sold through it, in currency: 0.0 for a corporate account, and null where sells_your_inbond_wine is false.' type: number nullable: true currency: description: Your market’s currency. type: string x-extensible-enum: - GBP - USD - HKD - SGD - EUR - AED - CNY Wine: type: object required: - lwin18 - wine_name - vintage - pack_size - producer - region - colour - product_url - market_price - bids - offers properties: lwin18: description: 'The 18-digit LWIN: wine, vintage and pack together. Match on all 18 digits.' type: string wine_name: description: Cru’s name for the wine. type: string nullable: true vintage: description: The vintage year. 1000 means non-vintage. type: integer nullable: true pack_size: description: Pack format, for example 6x75cl. type: string nullable: true producer: description: The producer. type: string nullable: true region: description: The region. type: string nullable: true colour: description: Red, white, rosé and so on. type: string nullable: true product_url: description: The wine’s page on the Cru storefront for the market you called. type: string format: uri nullable: true market_price: description: 'Always present: Cru’s market price in data.currency, or null when it has none.' type: number nullable: true bids: description: The bids on the wine, as GET /market/wines/{lwin18}/bids gives them. type: array items: $ref: '#/components/schemas/MarketBid' offers: description: The offers of the wine, as GET /market/wines/{lwin18}/offers gives them. type: array items: $ref: '#/components/schemas/MarketOffer' WineDetail: type: object required: - lwin18 - wine_name - vintage - pack_size - producer - region - colour - product_url - market_price - short_name - country - sub_region - is_cask - score - drinking_window - currency - last_trade - bids - offers properties: lwin18: description: 'The 18-digit LWIN: wine, vintage and pack together. Match on all 18 digits.' type: string wine_name: description: Cru’s name for the wine. type: string nullable: true vintage: description: The vintage year. 1000 means non-vintage. type: integer nullable: true pack_size: description: Pack format, for example 6x75cl. type: string nullable: true producer: description: The producer. type: string nullable: true region: description: The region. type: string nullable: true colour: description: Red, white, rosé and so on. type: string nullable: true product_url: description: The wine’s page on the Cru storefront for the market you called. type: string format: uri nullable: true market_price: description: 'Always present: Cru’s market price in data.currency, or null when it has none.' type: number nullable: true short_name: description: A shorter display name. type: string nullable: true country: description: Country of origin. type: string nullable: true sub_region: description: Sub-region or appellation. type: string nullable: true is_cask: description: Whether this is a cask rather than bottles. type: boolean score: description: A critic score. type: number nullable: true drinking_window: description: When to drink it. type: string nullable: true currency: description: The currency of the prices. type: string x-extensible-enum: - GBP - USD - HKD - SGD - EUR - AED - CNY last_trade: description: 'Always present: price and traded_at, or null.' nullable: true allOf: - $ref: '#/components/schemas/LastTrade' bids: description: The bids on the wine, as GET /market/wines/{lwin18}/bids gives them. type: array items: $ref: '#/components/schemas/MarketBid' offers: description: The offers of the wine, as GET /market/wines/{lwin18}/offers gives them. type: array items: $ref: '#/components/schemas/MarketOffer'