Introduction
The Trolley API gives you read-only access to UK grocery product and brand data.
It is built around simple REST principles. Every endpoint is a GET request, every response is JSON, and standard HTTP status codes tell you whether a request worked.
You can look products up by their Trolley product_id or by barcode, search products and brands by name, and list all the products of a brand.
Base URL
https://api.trolley.co.uk/api
Requests must use HTTPS. Plain HTTP requests are rejected with a HTTPS_REQUIRED error.
Append the endpoint path to the base URL. For example, to get a product profile:
GET https://api.trolley.co.uk/api/product/AAA268/profile
Authentication
Create an account and your keys in the dashboard. Each account gets a free sandbox key, and you can create live keys for real data.
Every request must include an Authorization header with your 64-character API key, using Bearer authentication. The key is sent as it is, without Base64 encoding.
Authorization: Bearer YOUR_API_KEY
curl -X GET "https://api.trolley.co.uk/api/product/AAA268/profile" \
-H "Authorization: Bearer YOUR_API_KEY"
Error Handling
Every response is a JSON object with a status field. A successful request returns HTTP 200, "status": "success" and a data object. A failed request returns an HTTP error code, "status": "error", a code string and a human-readable message.
{
"status": "error",
"code": "PRODUCT_NOT_FOUND",
"message": "No product was found with that product_id.",
"request_id": "9f2c41d0a7b3e655"
}
| HTTP | Code | Meaning |
|---|---|---|
| 400 | HTTPS_REQUIRED | The request was not made over HTTPS. |
| 400 | MISSING_PARAMETER | A required parameter, such as query, was not sent. |
| 401 | MISSING_API_KEY | No Authorization: Bearer header was sent. |
| 401 | INVALID_API_KEY | The API key is not valid or has been revoked. |
| 402 | INSUFFICIENT_CREDITS | Your balance is lower than the cost of the request. See Credits. |
| 404 | ENDPOINT_NOT_FOUND | The path does not match any endpoint. |
| 404 | PRODUCT_NOT_FOUND | No product matches the product_id or barcode. |
| 404 | BRAND_NOT_FOUND | No brand matches the brand_id. |
| 404 | SANDBOX_RECORD_UNAVAILABLE | A sandbox key asked for a record outside the samples. See Sandbox. |
| 405 | METHOD_NOT_ALLOWED | Only GET is supported. |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests. See Rate Limits. |
| 500 | SERVER_ERROR | Something went wrong on our side. |
4xx codes mean the request has invalid data, missing parameters or an authentication problem. 5xx codes mean an unexpected error on our side. Quote the request_id if you contact us about one.
Metadata
Every successful response includes a meta block next to the requested data.
| Field | Description |
|---|---|
api_key | A masked version of the key used for the request. |
api_key_name | The name the key was given. |
request_id | A unique ID for the request. Quote it when you contact us about a specific request. |
request_path | The endpoint path that ran. |
timestamp | When the request was processed, in ISO 8601 format (UTC). |
sandbox | true when the request used a sandbox key. |
credits.cost | The credits taken for this request. |
credits.remaining | Your credit balance after this request. |
"meta": {
"api_key": "33e5********************************************************fec3",
"api_key_name": "Production server",
"sandbox": false,
"request_id": "9f2c41d0a7b3e655",
"request_path": "/product/AAA268/profile",
"timestamp": "2026-11-11T14:32:08+00:00",
"credits": {
"cost": 1,
"remaining": 4999
}
}
Pagination
List endpoints return their results in a block with a pagination object and an items array. Use these query parameters to move through the results.
| Parameter | Default | Description |
|---|---|---|
page | 1 | The page number, from 1 to 1000. |
per_page | 20 | Items per page, from 1 to 100. |
"pagination": {
"page": 1,
"per_page": 20,
"total_items": 125,
"total_pages": 7
}
Rate Limits
Limits apply per API key across all requests. Each key can make 100 requests in any 10-minute period. The window slides, so a request frees up again 10 minutes after it was made.
Every response carries X-RateLimit-Limit and X-RateLimit-Remaining headers. Once you reach the limit, the API returns HTTP 429 with a Retry-After header giving the number of seconds until your next request will be accepted. Rejected requests don't count towards the limit, so retrying doesn't make the wait longer.
{
"status": "error",
"code": "RATE_LIMIT_EXCEEDED",
"message": "You have exceeded your request limit. Please wait before sending more requests.",
"request_id": "9f2c41d0a7b3e655"
}
Credits
Live requests are paid for with credits. You buy credits in the dashboard and they never expire.
| Endpoint | Cost |
|---|---|
GET /product/search | 1 credit |
GET /product/{product_id}/profile | 1 credit |
GET /barcode/{barcode}/profile | 1 credit |
GET /brand/search | 1 credit |
GET /brand/{brand_id}/profile | 1 credit |
GET /brand/{brand_id}/products | 2 credits |
Credits are only taken for successful requests. Errors, such as a product that isn't found, are free. Every successful response shows the cost and your remaining balance in meta.credits.
If your balance is lower than the cost, the API returns HTTP 402:
{
"status": "error",
"code": "INSUFFICIENT_CREDITS",
"message": "This request costs 2 credits and you have 1. Top up in your dashboard.",
"request_id": "9f2c41d0a7b3e655"
}
Sandbox
Every account gets a sandbox key in the dashboard. Sandbox requests use the same base URL and endpoints and return the same response format, but they are free and only see a small set of sample records. The dashboard also has a tester to try each endpoint in your browser.
| Sample | IDs |
|---|---|
| Products | AAA268, AXD157, AYR944, BCG688, BPD723, CAC091, AAA185 |
| Brands | 9224 (Tesco Pet), 9699 (Trooper) |
Searches with a sandbox key only return sample records. Asking for any other product or brand returns 404 SANDBOX_RECORD_UNAVAILABLE. Sandbox responses have "sandbox": true in meta, and sandbox keys share the same rate limit.
Product Search
Search products by name.
/product/search| Parameter | Required | Description |
|---|---|---|
query | Yes | Words from the product name, for example dog sticks. Very short words (under 3 characters) are ignored. Counting stops at 10,000 matches: when there are more, total_items is 10,000 and pagination.total_capped is true. |
page | No | See Pagination. |
per_page | No | See Pagination. |
Example request
curl -X GET "https://api.trolley.co.uk/api/product/search?query=dog%20sticks&per_page=5" \
-H "Authorization: Bearer YOUR_API_KEY"
Example response
{
"status": "success",
"query": "dog sticks",
"data": {
"search": {
"pagination": {
"page": 1,
"per_page": 5,
"total_items": 41,
"total_pages": 9
},
"items": [
{
"product_id": "AAA268",
"barcode": "5052909467342",
"name": "Tesco Daily Dental 7 Large Dog Sticks",
"brand": "Tesco Pet",
"size": "270g",
"price_min": 0.85,
"total_stores": 1
}
]
}
},
"meta": { "...": "..." }
}
Product Profile
Get the details of one product by its Trolley product_id.
/product/{product_id}/profile| Parameter | Required | Description |
|---|---|---|
product_id | Yes | The product's Trolley ID, up to 6 letters and digits, for example AAA268. |
Example request
curl -X GET "https://api.trolley.co.uk/api/product/AAA268/profile" \
-H "Authorization: Bearer YOUR_API_KEY"
Example response
{
"status": "success",
"product_id": "AAA268",
"data": {
"overview": {
"product_id": "AAA268",
"barcode": "5052909467342",
"name": "Tesco Daily Dental 7 Large Dog Sticks",
"names": ["Tesco Daily Dental 7 Large Dog Sticks"],
"brand": "Tesco Pet",
"size": "270g",
"quantity": "",
"category": "Pets",
"url": "tesco-7-dental-sticks-for-large-dogs",
"price_min": 0.85,
"price_savings": 0,
"total_stores": 1,
"rating": { "average": 4.8, "count": 97 },
"info": ""
}
},
"meta": { "...": "..." }
}
Response fields
| Field | Description |
|---|---|
name | The main product name. names lists every name held for the product. |
price_min | The lowest current price across stores, in GBP. |
price_savings | The saving against the usual price, in GBP. |
total_stores | The number of stores selling the product. |
rating | The average rating and the number of ratings. |
Product Profile by Barcode
Get the same product profile using the product's barcode.
/barcode/{barcode}/profile| Parameter | Required | Description |
|---|---|---|
barcode | Yes | The product's barcode, for example 5052909467342. |
Example request
curl -X GET "https://api.trolley.co.uk/api/barcode/5052909467342/profile" \
-H "Authorization: Bearer YOUR_API_KEY"
The response has the same shape as Product Profile, with barcode as the top-level identifier instead of product_id.
Brand Search
Find brands whose name starts with your search text.
/brand/search| Parameter | Required | Description |
|---|---|---|
query | Yes | The start of a brand name, for example Tesco. |
page | No | See Pagination. |
per_page | No | See Pagination. |
Example request
curl -X GET "https://api.trolley.co.uk/api/brand/search?query=Tesco%20Pet" \
-H "Authorization: Bearer YOUR_API_KEY"
Example response
{
"status": "success",
"query": "Tesco Pet",
"data": {
"search": {
"pagination": {
"page": 1,
"per_page": 20,
"total_items": 1,
"total_pages": 1
},
"items": [
{
"brand_id": 9224,
"name": "Tesco Pet",
"seo_url": "tesco-pet",
"product_count": 125
}
]
}
},
"meta": { "...": "..." }
}
Brand Profile
Get the details of one brand.
/brand/{brand_id}/profile| Parameter | Required | Description |
|---|---|---|
brand_id | Yes | The brand's ID, from Brand Search, for example 9224. |
Example request
curl -X GET "https://api.trolley.co.uk/api/brand/9224/profile" \
-H "Authorization: Bearer YOUR_API_KEY"
Example response
{
"status": "success",
"brand_id": 9224,
"data": {
"overview": {
"brand_id": 9224,
"name": "Tesco Pet",
"corrected_name": "Tesco Pet",
"seo_url": "tesco-pet",
"logo": null,
"wikipedia": null,
"description": null,
"product_count": 125
}
},
"meta": { "...": "..." }
}
Brand Products
List the products of a brand, in the order they were added.
/brand/{brand_id}/products| Parameter | Required | Description |
|---|---|---|
brand_id | Yes | The brand's ID, from Brand Search. |
page | No | See Pagination. |
per_page | No | See Pagination. |
Example request
curl -X GET "https://api.trolley.co.uk/api/brand/9224/products?per_page=2" \
-H "Authorization: Bearer YOUR_API_KEY"
Example response
{
"status": "success",
"brand_id": 9224,
"data": {
"products": {
"pagination": {
"page": 1,
"per_page": 2,
"total_items": 125,
"total_pages": 63
},
"items": [
{
"product_id": "AAA268",
"barcode": "5052909467342",
"name": "Tesco Daily Dental 7 Large Dog Sticks",
"brand": "Tesco Pet",
"size": "270g",
"price_min": 0.85,
"total_stores": 1
}
]
}
},
"meta": { "...": "..." }
}