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"
Never share your key or put it in client-side code such as browser JavaScript. Keep it in an environment variable on your server and call the API from there.

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"
}
HTTPCodeMeaning
400HTTPS_REQUIREDThe request was not made over HTTPS.
400MISSING_PARAMETERA required parameter, such as query, was not sent.
401MISSING_API_KEYNo Authorization: Bearer header was sent.
401INVALID_API_KEYThe API key is not valid or has been revoked.
402INSUFFICIENT_CREDITSYour balance is lower than the cost of the request. See Credits.
404ENDPOINT_NOT_FOUNDThe path does not match any endpoint.
404PRODUCT_NOT_FOUNDNo product matches the product_id or barcode.
404BRAND_NOT_FOUNDNo brand matches the brand_id.
404SANDBOX_RECORD_UNAVAILABLEA sandbox key asked for a record outside the samples. See Sandbox.
405METHOD_NOT_ALLOWEDOnly GET is supported.
429RATE_LIMIT_EXCEEDEDToo many requests. See Rate Limits.
500SERVER_ERRORSomething 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.

FieldDescription
api_keyA masked version of the key used for the request.
api_key_nameThe name the key was given.
request_idA unique ID for the request. Quote it when you contact us about a specific request.
request_pathThe endpoint path that ran.
timestampWhen the request was processed, in ISO 8601 format (UTC).
sandboxtrue when the request used a sandbox key.
credits.costThe credits taken for this request.
credits.remainingYour 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.

ParameterDefaultDescription
page1The page number, from 1 to 1000.
per_page20Items 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.

EndpointCost
GET /product/search1 credit
GET /product/{product_id}/profile1 credit
GET /barcode/{barcode}/profile1 credit
GET /brand/search1 credit
GET /brand/{brand_id}/profile1 credit
GET /brand/{brand_id}/products2 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.

SampleIDs
ProductsAAA268, AXD157, AYR944, BCG688, BPD723, CAC091, AAA185
Brands9224 (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 Profile

Get the details of one product by its Trolley product_id.

GET/product/{product_id}/profile
ParameterRequiredDescription
product_idYesThe 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

FieldDescription
nameThe main product name. names lists every name held for the product.
price_minThe lowest current price across stores, in GBP.
price_savingsThe saving against the usual price, in GBP.
total_storesThe number of stores selling the product.
ratingThe average rating and the number of ratings.

Product Profile by Barcode

Get the same product profile using the product's barcode.

GET/barcode/{barcode}/profile
ParameterRequiredDescription
barcodeYesThe 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 Profile

Get the details of one brand.

GET/brand/{brand_id}/profile
ParameterRequiredDescription
brand_idYesThe 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.

GET/brand/{brand_id}/products
ParameterRequiredDescription
brand_idYesThe brand's ID, from Brand Search.
pageNoSee Pagination.
per_pageNoSee 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": { "...": "..." }
}