This documentation will demonstrate the process and code needed to integrate with Bordeaux Index's APIsThe APIs are a suite of interfaces that allow you to view and interact with BI's marketplace and your portfolio.To facilitate integrations there are testing environments that allows you to test the functionality of the APIs without the risks of production integration. which we'll use through the code snippets bellow, we recommend integrating with the testing servers and only then with live ones.
If you want to integrate your system with our APIs please contact us at [email protected]and we'll help you set up on our testing enviorment using mock data which you can use to make your system production ready ahead of trading on live servers!Once you're happy with the performance and functionality of your application you'll be asked register and create credentials for the live servers which you can change for the testing credentials in your application and you'll be ready to trade! We're here to help, so if you have questions or suggestions please reach out!
User Routes
The user routes can be accessed through /v2/user and provide you with endpoints to manage your account.To access protected market and trading endpoints you need to register and login which will provide you with a authentication token, this then be used as a header to authnticate yourself to the server.
POST
/v2/user/register
This is the entry point to integrating with the APIs. Once you've sent the POST request sucessfully, you'll recieve an email confirmation which needs to be confirmed before continuing,
once accepted please contact us at [email protected] as your account now needs to be internally approved before you can use it. You'll recieve an email when your testing or live account has been approved, at which point you can use the credentials to login.
NOTE:Approval is needed in both Test and Live servers, please contact us for both.
The response will contain a token property (read and printed above), which should be sent as an Authorization header to query protected routes. The token has a 24 hours expiry, after which you'll be required to login again and replace it with your old token.
POST
/v2/user/resendVerificationEmail
If you need to resend the verification email, you can use the POST /v2/user/resendVerificationEmail endpoint. This endpoint requires the email address used during registration. See the example code below for reference.
import requests
# URL of the API endpoint
url = "https://uat-api.biwine.com/v2/user/resendVerificationEmail"
# JSON body to be sent in the request
payload = {
"email": "string",
"salesLedger": "string",
"purchaseLedger": "string"
}
# Headers, if required
headers = {
"Content-Type": "application/json"
}
# Send the POST request
response = requests.post(url, json=payload, headers=headers)
# Print the response status and body
print("Status Code:", response.status_code)
print("Response Body:", response.text)
If you need to request a password reset, you can use the POST /v2/user/requestPasswordReset endpoint. This endpoint requires the email address associated with the account. See the example code below for reference.
On successful response, the verification email will be resent to the provided email address. Make sure to check your inbox and spam folder for the email.
The producer routes can be accessed through /v2/producer and provide you with endpoints to view our producer catalogue. The in-query parameters page and limit are supported and default to 0 and 50 respectively.
GET
/producer
This endpoint will provide you with a full list of all producers available on the platform. The bellow code demonstrates how to access the endpoint and prints the name of each producer after querying the endpoint
import requests
# API endpoint
url = "https://uat-api.biwine.com/v2/producer"
try:
# Send GET request
response = requests.get(url)
response.raise_for_status() # Raise an error for HTTP errors
# Parse JSON response
data = response.json()
# Extract and print names from 'results'
results = data.get("results", [])
for item in results:
name = item.get("name")
if name:
print(name)
except requests.exceptions.RequestException as e:
print("HTTP Request failed:", e)
except ValueError:
print("Invalid JSON response")
Alternatively you can query a specific producer using the /v2/producer/{bipid} endpoint. The bellow code demonstrates how to access the endpoint and prints the name of the producer.
import requests
# Replace with desired bipId
bip_id = 231451
# Construct the URL
url = f"https://uat-api.biwine.com/v2/producer/{bip_id}"
try:
# Send GET request
response = requests.get(url)
response.raise_for_status() # Raise error for HTTP error codes
# Parse JSON response
data = response.json()
# Print the producer's name
print("Producer Name:", data.get("name"))
except requests.exceptions.RequestException as e:
print("HTTP Request failed:", e)
except ValueError:
print("Invalid JSON response")
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.json.JSONObject;
public class GetProducerById {
public static void main(String[] args) {
// Replace with the desired bipId
int bipId = 231451;
String url = "https://uat-api.biwine.com/v2/producer/" + bipId;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.GET()
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JSONObject json = new JSONObject(response.body());
String name = json.getString("name");
System.out.println("Producer Name: " + name);
} else {
System.out.println("Request failed with status code: " + response.statusCode());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Market Routes
Using the token from the step above we're now able to view and interact with BI's stock.
The market routes provide a way to query and view the markets, they are protected and require an authentication token to be sent in the headers of the request.
GET
/v2/market
The endpoint is the main entry point for accessing market data. It provides a list of all available wines, their product details and bids & offers available. It supports pagination with in-query parameters page and limit which default to 0 and 50 respectively.
See bellow code which demonstrates how to access the endpoint and iterate through the list of wines printing the name to the console.
import requests
# Your Bearer token from login
token = "YOUR_JWT_TOKEN_HERE or ENV VARIABLE"
# Endpoint
url = "https://uat-api.biwine.com/v2/market"
# Headers
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/json"
}
# Make GET request
response = requests.get(url, headers=headers)
# Handle response
if response.status_code == 200:
try:
data = response.json()
results = data.get("results", [])
if not results:
print("No results found.")
else:
print("Wine names:")
for item in results:
name = item.get("productName", "Unknown")
print("-", name)
except ValueError:
print("Invalid JSON in response.")
else:
print(f"Request failed. Status code: {response.status_code}")
print(response.text)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.json.JSONArray;
import org.json.JSONObject;
public class GetWineNames {
public static void main(String[] args) {
String token = "YOUR_JWT_TOKEN_HERE or ENV VARIABLE"; // Replace with actual token
String url = "https://uat-api.biwine.com/v2/market";
try {
// Create HTTP client
HttpClient client = HttpClient.newHttpClient();
// Create GET request with Authorization header
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + token)
.header("Accept", "application/json")
.GET()
.build();
// Send request and get response
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JSONObject json = new JSONObject(response.body());
JSONArray results = json.optJSONArray("results");
if (results == null || results.isEmpty()) {
System.out.println("No wine results found.");
} else {
System.out.println("Wine names:");
for (int i = 0; i < results.length(); i++) {
JSONObject item = results.getJSONObject(i);
String productName = item.optString("productName", "Unknown");
System.out.println("- " + productName);
}
}
} else {
System.out.println("Request failed with status: " + response.statusCode());
System.out.println("Body: " + response.body());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
GET
/v2/market/lwin18/{lwin18}
This endpoint allows you to view the details of a specific wine using its lwin18 code, returning the same information and details as the /v2/market endpoint but only for the specific lwin18 market. The bellow code demonstrates how to access the endpoint and prints the lwinProductName property.
import requests
# Replace with your actual token and lwin18 value
token = "YOUR_JWT_TOKEN_HERE or ENV VARIABLE"
lwin18 = "100006920071200750"
# API endpoint
url = f"https://uat-api.biwine.com/v2/market/lwin18/{lwin18}"
# Headers including the Bearer token
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/json"
}
# Send GET request
response = requests.get(url, headers=headers)
# Handle response
if response.status_code == 200:
data = response.json()
product_name = data.get("lwinProductName")
if product_name:
print("Product Name:", product_name)
else:
print("lwinProductName not found in response.")
else:
print("Request failed with status:", response.status_code)
print("Response:", response.text)
const token = "YOUR_JWT_TOKEN_HERE"; // Replace with your actual token
const lwin18 = "100006920071200750"; // Example lwin18 value
const url = `https://uat-api.biwine.com/v2/market/lwin18/${lwin18}`;
fetch(url, {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Accept": "application/json"
}
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(data => {
const productName = data.lwinProductName;
if (productName) {
console.log("Product Name:", productName);
} else {
console.log("lwinProductName not found in response.");
}
})
.catch(error => {
console.error("Error:", error);
});
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.json.JSONArray;
import org.json.JSONObject;
public class GetWineNames {
public static void main(String[] args) {
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."; // Replace with actual token
String url = "https://uat-api.biwine.com/v2/market";
try {
// Create HTTP client
HttpClient client = HttpClient.newHttpClient();
// Create GET request with Authorization header
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + token)
.header("Accept", "application/json")
.GET()
.build();
// Send request and get response
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JSONObject json = new JSONObject(response.body());
JSONArray results = json.optJSONArray("results");
if (results == null || results.isEmpty()) {
System.out.println("No wine results found.");
} else {
System.out.println("Wine names:");
for (int i = 0; i < results.length(); i++) {
JSONObject item = results.getJSONObject(i);
String productName = item.optString("productName", "Unknown");
System.out.println("- " + productName);
}
}
} else {
System.out.println("Request failed with status: " + response.statusCode());
System.out.println("Body: " + response.body());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
GET
/v2/market/delta
This endpoint allows you to view the delta of the market from a ISO time stamp onwards. The result will be list of wines like the /market route but with an additional 'changesSince' property that cronologically shows the changes to the wine's orders since the time stamp. The bellow code demonstrates how to access the endpoint and prints the time that the last change happened for the first wine in the list.
It requires a mandatory in-query parameter 'fromDateTime' which should be an ISO date. additionally the optional in-query parameters page, limit and marketDepth are also supported/
import requests
# Replace with your actual token
token = "YOUR_JWT_TOKEN_HERE or ENV VARIABLE"
# ISO-formatted datetime query param
from_datetime = "2025-04-30T00:00:00.000Z" # adjust as needed
# API endpoint with query param
url = "https://uat-api.biwine.com/v2/market/delta"
params = {
"fromDateTime": from_datetime
}
# Authorization headers
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/json"
}
# Send GET request
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
data = response.json()
results = data.get("results", [])
if results:
first_result = results[0]
changes = first_result.get("changesSince", {})
bids = changes.get("bids", [])
offers = changes.get("offers", [])
# Check for time in bids or offers
if bids:
print("First bid change time:", bids[0].get("time"))
elif offers:
print("First offer change time:", offers[0].get("time"))
else:
print("No bid or offer changes found in changesSince.")
else:
print("No results in response.")
else:
print("Request failed with status:", response.status_code)
print("Response:", response.text)
This endpoint provides a list of all supported markets and their details. It allows you to query the markets that are currently available for trading. The code below demonstrates how to access the endpoint and prints the market names.
import requests
# URL endpoint
url = "https://uat-api.biwine.com/v2/market/supported"
# Replace this with your actual Bearer token
auth_token = "YOUR_ACCESS_TOKEN_HERE"
# Set headers with Authorization
headers = {
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json"
}
try:
# Send GET request
response = requests.get(url, headers=headers)
response.raise_for_status()
# Parse JSON response
data = response.json()
results = data.get("results", [])
# Print lwin18 for each item
for item in results:
lwin18 = item.get("lwin18")
if lwin18:
print("lwin18:", lwin18)
except requests.exceptions.RequestException as e:
print("HTTP request failed:", e)
except ValueError:
print("Failed to parse JSON response")
const url = "https://uat-api.biwine.com/v2/market/supported";
// Replace this with your actual Bearer token
const token = "YOUR_ACCESS_TOKEN_HERE";
fetch(url, {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
}
})
.then(response => {
if (!response.ok) {
throw new Error(`Request failed with status: ${response.status}`);
}
return response.json();
})
.then(data => {
const results = data.results || [];
results.forEach(item => {
if (item.lwin18) {
console.log("lwin18:", item.lwin18);
}
});
})
.catch(error => {
console.error("Error:", error.message);
});
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.json.JSONArray;
import org.json.JSONObject;
public class GetSupportedMarketItems {
public static void main(String[] args) {
// Replace with your actual token
String token = "YOUR_ACCESS_TOKEN_HERE";
String url = "https://uat-api.biwine.com/v2/market/supported";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + token)
.header("Content-Type", "application/json")
.GET()
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JSONObject json = new JSONObject(response.body());
JSONArray results = json.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
JSONObject item = results.getJSONObject(i);
System.out.println("lwin18: " + item.getLong("lwin18"));
}
} else {
System.out.println("Request failed with status code: " + response.statusCode());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Trading Routes
The trading routes allow you to place, alter, delete and view your offers and bids on the market.
These routes too are protected routes and require the token to be sent as an Authorization header in the request.
GET
/v2/trading/positions/{side}
This end point allows you to view all of your bids or offers on the market. The side parameter can be either 'bid' or 'offer' and will return a list of all of your bids or offers respectively. The bellow code demonstrates how to access the endpoint and prints the lwinProductName property for each bid or offer.
The in-query parameters page and limit are supported and default to 0 and 50 respectively, and additionally you can filter your super-set by using optional fromDate and toDate parameters which should be in yyyy-MM-dd format, note that fromDate is required if toDate is used.
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import org.json.JSONArray;
import org.json.JSONObject;
public class TradingPositionsFetcher {
public static void main(String[] args) {
// Replace these values as needed
String side = "bid"; // or "offer"
int page = 1;
int limit = 50;
String token = "YOUR_ACCESS_TOKEN_HERE";
try {
String url = String.format(
"https://uat-api.biwine.com/v2/trading/positions/%s?page=%d&limit=%d",
URLEncoder.encode(side, StandardCharsets.UTF_8),
page,
limit
);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + token)
.header("Content-Type", "application/json")
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JSONObject json = new JSONObject(response.body());
JSONArray results = json.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
JSONObject item = results.getJSONObject(i);
long lwin18 = item.getLong("lwin18");
System.out.println("lwin18: " + lwin18);
}
} else {
System.out.println("Request failed with status code: " + response.statusCode());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
GET
/v2/trading/{side}/{orderId}
This end point allows you to query the state of an order that you've raised, side can be either 'bid' or 'offer' and orderId is the id of the order that you want to query. The bellow code demonstrates how to access the endpoint and prints the status property.
import requests
side = "bid" # or "offer"
order_id = 94
auth_token = "YOUR_ACCESS_TOKEN_HERE"
url = f"https://uat-api.biwine.com/v2/trading/{side}/{order_id}"
headers = {
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json"
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
data = response.json()
lwin18 = data.get("lwin18")
if lwin18:
print("lwin18:", lwin18)
else:
print("lwin18 not found in response")
except requests.exceptions.RequestException as e:
print("HTTP request failed:", e)
except ValueError:
print("Invalid JSON response")
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.json.JSONObject;
public class TradingOrderFetcher {
public static void main(String[] args) {
String side = "bid"; // or "offer"
int orderId = 94;
String token = "YOUR_ACCESS_TOKEN_HERE";
String url = String.format("https://uat-api.biwine.com/v2/trading/%s/%d", side, orderId);
try {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + token)
.header("Content-Type", "application/json")
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JSONObject json = new JSONObject(response.body());
if (json.has("lwin18")) {
System.out.println("lwin18: " + json.getLong("lwin18"));
} else {
System.out.println("lwin18 not found in response");
}
} else {
System.out.println("Request failed with status code: " + response.statusCode());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
The trading routes allow you to place, alter, delete and view your offers and bids on the market.
These routes too are protected routes and require the token to be sent as an Authorization header in the request.
POST
/v2/trading/{lwin18}/bid
This endpoint allows you to place a bid for a specific wine using its lwin18 code. The body of the request should include the details of the bid, such as price and quantity. The code below demonstrates how to access the endpoint and prints the order id.
import requests
# Replace with your actual LWIN18 identifier
lwin18 = "12345678901234"
# API endpoint
url = f"https://uat-api.biwine.com/v2/trading/lwin18/{lwin18}/bid"
# Request payload
payload = {
"price": 940,
"quantity": 1,
"dutyStatus": "IB",
"caseCondition": "OC",
"bottleCondition": "PR",
"availableImmediately": False,
"fillOrKill": False,
"customerRef": "string"
}
# Replace with a valid Bearer token or other auth if required
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN" # Replace with actual token
}
# Send POST request
response = requests.post(url, json=payload, headers=headers)
# Process response
if response.status_code == 200:
try:
data = response.json()
print("orderId:", data.get("orderId"))
except ValueError:
print("Failed to decode JSON response")
else:
print(f"Request failed with status code {response.status_code}: {response.text}")
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.JSONObject;
public class PostBidRequest {
public static void main(String[] args) {
String lwin18 = "12345678901234"; // Replace with your actual LWIN18
String apiUrl = "https://uat-api.biwine.com/v2/trading/lwin18/" + lwin18 + "/bid";
String token = "YOUR_API_TOKEN"; // Replace with your actual Bearer token
try {
// Create URL and connection
URL url = new URL(apiUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// Set request method and headers
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Authorization", "Bearer " + token);
conn.setDoOutput(true);
// Create JSON request body
JSONObject json = new JSONObject();
json.put("price", 940);
json.put("quantity", 1);
json.put("dutyStatus", "IB");
json.put("caseCondition", "OC");
json.put("bottleCondition", "PR");
json.put("availableImmediately", false);
json.put("fillOrKill", false);
json.put("customerRef", "string");
// Send request
try (OutputStream os = conn.getOutputStream()) {
byte[] input = json.toString().getBytes("utf-8");
os.write(input, 0, input.length);
}
// Read response
int status = conn.getResponseCode();
if (status == 200) {
try (BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "utf-8"))) {
StringBuilder response = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
response.append(line.trim());
}
// Parse and print orderId
JSONObject responseJson = new JSONObject(response.toString());
System.out.println("orderId: " + responseJson.getInt("orderId"));
}
} else {
System.out.println("Request failed with status code " + status);
}
conn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
POST
/v2/trading/{lwin18}/offer
This endpoint allows you to place an offer for a specific wine using its lwin18 code. The body of the request should include the details of the bid, such as price and quantity. The code below demonstrates how to access the endpoint and prints the quantity matched.
import requests
lwin18 = "100006920071200750" # Replace with actual LWIN18
auth_token = "YOUR_JWT_TOKEN_HERE"
url = f"https://uat-api.biwine.com/v2/trading/lwin18/{lwin18}/offer"
headers = {
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json"
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
data = response.json()
quantity = data.get("quantity")
if quantity is not None:
print("Quantity:", quantity)
else:
print("Quantity not found in response.")
except requests.exceptions.RequestException as e:
print("HTTP request failed:", e)
except ValueError:
print("Invalid JSON response")
const lwin18 = "100006920071200750"; // Replace with actual LWIN18
const token = "YOUR_JWT_TOKEN_HERE";
const url = `https://uat-api.biwine.com/v2/trading/lwin18/${lwin18}/offer`;
fetch(url, {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
}
})
.then(response => {
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
return response.json();
})
.then(data => {
if ("quantity" in data) {
console.log("Quantity:", data.quantity);
} else {
console.log("Quantity not found in response");
}
})
.catch(error => {
console.error("Error:", error.message);
});
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.json.JSONObject;
public class OfferQuantityFetcher {
public static void main(String[] args) {
String lwin18 = "100006920071200750"; // Replace with actual LWIN18
String token = "YOUR_JWT_TOKEN_HERE";
String url = String.format("https://uat-api.biwine.com/v2/trading/lwin18/%s/offer", lwin18);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + token)
.header("Content-Type", "application/json")
.GET()
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JSONObject json = new JSONObject(response.body());
if (json.has("quantity")) {
int quantity = json.getInt("quantity");
System.out.println("Quantity: " + quantity);
} else {
System.out.println("Quantity not found in response.");
}
} else {
System.out.println("Request failed with status code: " + response.statusCode());
}
} catch (Exception e) {
System.out.println("Error during HTTP request:");
e.printStackTrace();
}
}
}
POST
/v2/trading/bordeauxCode/{bordeauxCode}/bid
This endpoint allows you to place an bid for a specific wine using its BordeauxCode code. The body of the request should include the details of the bid same as lwin18, such as price and quantity. The code below demonstrates how to access the endpoint and prints the quantity matched.
import requests
# Replace with actual bordeauxCode and token
bordeauxCode = "12345"
auth_token = "YOUR_JWT_TOKEN_HERE"
url = f"https://uat-api.biwine.com/v2/trading/bordeauxCode/{bordeauxCode}/bid"
headers = {
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json"
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
data = response.json()
quantity_matched = data.get("quantityMatched")
if quantity_matched is not None:
print("quantityMatched:", quantity_matched)
else:
print("quantityMatched not found in response.")
except requests.exceptions.RequestException as e:
print("HTTP request failed:", e)
except ValueError:
print("Invalid JSON response")
const bordeauxCode = "12345"; // Replace with actual bordeauxCode
const token = "YOUR_JWT_TOKEN_HERE";
const url = `https://uat-api.biwine.com/v2/trading/bordeauxCode/${bordeauxCode}/bid`;
fetch(url, {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
}
})
.then(response => {
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
return response.json();
})
.then(data => {
if ("quantityMatched" in data) {
console.log("quantityMatched:", data.quantityMatched);
} else {
console.log("quantityMatched not found in response");
}
})
.catch(error => {
console.error("Error:", error.message);
});
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.json.JSONObject;
public class QuantityMatchedFetcher {
public static void main(String[] args) {
String bordeauxCode = "12345"; // Replace with actual bordeauxCode
String token = "YOUR_JWT_TOKEN_HERE";
String url = String.format("https://uat-api.biwine.com/v2/trading/bordeauxCode/%s/bid", bordeauxCode);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + token)
.header("Content-Type", "application/json")
.GET()
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JSONObject json = new JSONObject(response.body());
if (json.has("quantityMatched")) {
int quantityMatched = json.getInt("quantityMatched");
System.out.println("quantityMatched: " + quantityMatched);
} else {
System.out.println("quantityMatched not found in response.");
}
} else {
System.out.println("Request failed with status code: " + response.statusCode());
}
} catch (Exception e) {
System.out.println("Error during HTTP request:");
e.printStackTrace();
}
}
}
POST
/v2/trading/bordeauxCode/{bordeauxCode}/offer
This endpoint allows you to place offers for a specific Bordeaux Code. The bordeauxCode parameter specifies the wine, and the side parameter can be either 'bid' or 'offer'. The bellow code demonstrates how to access the endpoint and prints the quantity matched.
import requests
# Replace with actual bordeauxCode and token
bordeauxCode = "12345"
auth_token = "YOUR_JWT_TOKEN_HERE"
url = f"https://uat-api.biwine.com/v2/trading/bordeauxCode/{bordeauxCode}/offer"
headers = {
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json"
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
data = response.json()
quantity_matched = data.get("quantityMatched")
if quantity_matched is not None:
print("quantityMatched:", quantity_matched)
else:
print("quantityMatched not found in response.")
except requests.exceptions.RequestException as e:
print("HTTP request failed:", e)
except ValueError:
print("Invalid JSON response")
const bordeauxCode = "12345"; // Replace with actual bordeauxCode
const token = "YOUR_JWT_TOKEN_HERE";
const url = `https://uat-api.biwine.com/v2/trading/bordeauxCode/${bordeauxCode}/offer`;
fetch(url, {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
}
})
.then(response => {
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
return response.json();
})
.then(data => {
if ("quantityMatched" in data) {
console.log("quantityMatched:", data.quantityMatched);
} else {
console.log("quantityMatched not found in response");
}
})
.catch(error => {
console.error("Error:", error.message);
});
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.json.JSONObject;
public class QuantityMatchedFetcher {
public static void main(String[] args) {
String bordeauxCode = "12345"; // Replace with actual bordeauxCode
String token = "YOUR_JWT_TOKEN_HERE";
String url = String.format("https://uat-api.biwine.com/v2/trading/bordeauxCode/%s/offer", bordeauxCode);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + token)
.header("Content-Type", "application/json")
.GET()
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JSONObject json = new JSONObject(response.body());
if (json.has("quantityMatched")) {
int quantityMatched = json.getInt("quantityMatched");
System.out.println("quantityMatched: " + quantityMatched);
} else {
System.out.println("quantityMatched not found in response.");
}
} else {
System.out.println("Request failed with status code: " + response.statusCode());
}
} catch (Exception e) {
System.out.println("Error during HTTP request:");
e.printStackTrace();
}
}
}
DELETE
/v2/trading/bid/{orderId}
This endpoint allows you to delete a bid using the orderId. The code bellow delets a bid and checks if the status is 200 (OK).
import requests
orderId = "12345" # Replace with actual orderId
auth_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVC..."
url = f"https://uat-api.biwine.com/v2/trading/bid/{orderId}"
headers = {
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json"
}
try:
response = requests.delete(url, headers=headers)
if response.status_code == 200:
print("Delete request successful.")
else:
print(f"Delete request failed with status code: {response.status_code}")
except requests.exceptions.RequestException as e:
print("HTTP request failed:", e)
This endpoint allows you to modify an existing trading bid using an orderId. The body of the request should include the updated details, such as price or quantity. Below is the code to access the endpoint, change quantity and print the updated order's status.
import requests
orderId = "12345" # Replace with actual orderId
auth_token = "YOUR_JWT_TOKEN_HERE"
url = f"https://uat-api.biwine.com/v2/trading/bid/{orderId}"
headers = {
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json"
}
data = {
"quantity": 3
}
try:
response = requests.patch(url, headers=headers, json=data)
if response.status_code == 200:
print("Patch request successful.")
else:
print(f"Patch request failed with status code: {response.status_code}")
except requests.exceptions.RequestException as e:
print("HTTP request failed:", e)
This endpoint allows you to modify an existing trading offer using an orderId. The body of the request should include the updated details, such as price or quantity. Below is the code to access the endpoint, change price and print the updated order's status.
POST
/v2/trading/portfolioRef/{portfolioRef}/offer
This endpoint allows submit a new offer to the market using the portfolioRef. The body of the request should include the details of the offer, such as price and quantity, as any offer would. The code below demonstrates how to access the endpoint and prints if the request was sucessful.
The post trade routes allow you to view your trades once matched and removed from the marketplace.
GET
/v2/postTrade
This endpoint allows you to retrieve a list of all YOUR post-trade activities, such as completed trades and settlements. The response includes details like trade ID, wine details, and settlement status. Below is the code to access the endpoint and print the trade IDs.
The in-query parameters page and limit are supported and default to 0 and 50 respectively, and additionally you can filter your super-set by using optional fromDate and toDate parameters which should be in yyyy-MM-dd format, note that fromDate is required if toDate is used.
This endpoint allows you to retrieve the current foreign exchange rates for supported currencies. The response includes details like currency pairs and their exchange rates. Below is the code to access the endpoint and print the exchange rates.
The manadatory in-query parameters from and to are necessary and possible values are USD, GBP, EUR, HKD, CHF, SGD, AUD, CAD, JPY, DKK and NZD.
import requests
auth_token = "YOUR_JWT_TOKEN_HERE"
url = "https://uat-api.biwine.com/v2/fxRate"
params = {
"from": "GBP",
"to": "EUR"
}
headers = {
"Authorization": f"Bearer {auth_token}"
}
try:
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
data = response.json()
rate = data.get("rate")
if rate is not None:
print(f"Exchange rate from GBP to EUR: {rate}")
else:
print("Rate not found in response.")
except requests.exceptions.RequestException as e:
print("HTTP request failed:", e)
except ValueError:
print("Invalid JSON response")
const token = "YOUR_JWT_TOKEN_HERE";
const url = "https://uat-api.biwine.com/v2/fxRate?from=GBP&to=EUR";
fetch(url, {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
}
})
.then(response => {
if (response.ok) {
return response.json();
} else {
console.error("Request failed with status:", response.status);
return null;
}
})
.then(data => {
if (data && data.rate !== undefined) {
console.log(`Exchange rate from GBP to EUR: ${data.rate}`);
} else {
console.log("Rate not found in response.");
}
})
.catch(error => {
console.error("Request error:", error);
});
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class FxRateRequest {
public static void main(String[] args) {
String token = "YOUR_JWT_TOKEN_HERE";
String url = "https://uat-api.biwine.com/v2/fxRate?from=GBP&to=EUR";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + token)
.GET()
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(response.body());
if (root.has("rate")) {
double rate = root.get("rate").asDouble();
System.out.println("Exchange rate from GBP to EUR: " + rate);
} else {
System.out.println("Rate not found in response.");
}
} else {
System.out.println("Request failed with status code: " + response.statusCode());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Portfolio Routes
GET
/v2/portfolio
This endpoint allows you to retrieve your Bordeaux Index portfolio. The in-query parameters page and limit are supported and default to 0 and 50 respectively.
import requests
# Replace with your actual Bearer token
auth_token = "YOUR_JWT_TOKEN_HERE"
url = "https://uat-api.biwine.com/v2/portfolio"
headers = {
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json"
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
data = response.json()
results = data.get("results", [])
if results:
for wine in results:
print("Product Name:", wine.get("productName", "N/A"))
else:
print("No results found.")
except requests.exceptions.RequestException as e:
print("HTTP request failed:", e)
except ValueError:
print("Invalid JSON response")
This endpoint allows you to view a single item in your portfolio. The optional in-query parameter marketDepth to specify the depth of the market data to be returned, which defaults to all if not sent.
import requests
portfolio_ref = "ST_1234_3" # Replace with actual portfolioRef
auth_token = "YOUR_JWT_TOKEN_HERE"
url = f"https://uat-api.biwine.com/v2/portfolio/{portfolio_ref}"
headers = {
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json"
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
data = response.json()
product_name = data.get("productName")
if product_name:
print("Product Name:", product_name)
else:
print("productName not found in response.")
except requests.exceptions.RequestException as e:
print("HTTP request failed:", e)
except ValueError:
print("Invalid JSON response")
const fetch = require('node-fetch'); // Only required in Node.js
const portfolioRef = 'ST_1234_3'; // Replace with actual portfolioRef
const authToken = 'YOUR_JWT_TOKEN_HERE';
const url = `https://uat-api.biwine.com/v2/portfolio/${portfolioRef}`;
fetch(url, {
method: 'GET',
headers: {
'Authorization': `Bearer ${authToken}`,
'Content-Type': 'application/json'
}
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => {
if (data.productName) {
console.log('Product Name:', data.productName);
} else {
console.log('productName not found in response.');
}
})
.catch(error => {
console.error('Request failed:', error.message);
});
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.json.JSONObject;
public class PortfolioFetcher {
public static void main(String[] args) {
String portfolioRef = "ST_1234_3"; // Replace with actual portfolioRef
String authToken = "YOUR_JWT_TOKEN_HERE";
String url = "https://uat-api.biwine.com/v2/portfolio/" + portfolioRef;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + authToken)
.header("Content-Type", "application/json")
.GET()
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JSONObject json = new JSONObject(response.body());
if (json.has("productName")) {
String productName = json.getString("productName");
System.out.println("Product Name: " + productName);
} else {
System.out.println("productName not found in response.");
}
} else {
System.out.println("HTTP request failed with status code: " + response.statusCode());
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
Error
Sorry but we've had a problem processing your request.
Please refresh to try again.
If the issue reoccurs, please contact us at +44 (0) 20 7269 0700 or email [email protected] and we will do our best to resolve the issue for you.
The wine has been added to your order.
Please carry on trading or go to My Basket to confirm.
My Delivery
Your instruction has been processed and a confirmation has been sent to your email address.
Valuation Request
The Bordeaux Index recommended valuation is calculated from a wide set of proprietary and public data to give the most accurate and dynamic pricing available. For this item, we need to investigate available price quality. The team will review and confirm a valuation for you.
Valuation Received
A valuation for your item has been identified.
Friendly Reminder - Automated Storage Payments
To benefit from our competitive storage rate of £14.50 annually (ex. VAT) per 12 bottle case
Please ensure you have a payment card saved to your account.
Accounts without a saved card in July will incur additional charges per case (further detail here.)