Developers
PetFoodFix API
Read-only JSON endpoints behind the PetFoodFix catalogue search: commercial pet food labels (ingredients, declared protein, fat, fibre, ash, moisture, kcal/100g) and the deterministic educational score for dog foods. No API key. The machine-readable contract is /openapi.json (OpenAPI 3.1).
When to use it
- An owner names a dog or cat food and wants to know what its label declares.
- Comparing the label data of two or more foods sold in the UK, Brazil, the US, Canada or Portugal.
- Finding a product page to send the owner to (build it from
slug, e.g. /uk/dogs/foods/{slug}).
It is not for feeding plans or health questions. Puppies under 12 months, pregnant or lactating animals, and animals with a diagnosed condition or on prescription food need a veterinary professional. Scores describe the label, not the animal.
Basics
- Base URL:
https://petfoodfix.com. HTTPS only, GET only. - Authentication: none.
- Responses:
application/json. A value the label does not declare is left out; the one exception is kcal, which may be calculated when the pack declares no energy. - Cat products never carry a score.
Endpoints
Search pet food products by brand and product name
GET /api/foods/products/search · operationId searchFoodProducts
Free-text search over active products in one market. Returns up to 20 products ranked by match, with label data and, for dog foods, the educational score. When fewer than 5 products match, near-miss spellings are appended to `products` (`matchType` `strong_similar` or `possible_match`) and also listed in `fuzzySuggestions`, for the user to confirm; never treat them as the product the user meant. `matchType` `exact` means the product name contains the query text.
| Parameter | Type | Meaning |
|---|
| q | string (max 120) | Brand and/or product name, e.g. `royal canin giant puppy`. Empty returns a filtered list. |
| market | uk | br | us | ca | pt | other | Catalogue market. Any value not in this list falls back to `uk`. |
| species | dog | cat | Animal the food is for. Cat results never include a score. |
| brand | string (max 80) | Keep only brands whose name contains this text (case-insensitive). |
| format | string | Exact food format as stored, e.g. `dry` or `wet`. |
| life_stage | string | Exact life stage as stored, e.g. `adult`, `puppy`, `senior`. |
| completeness | string | Exact completeness statement as stored, e.g. `complete` or `complementary`. |
| verification_status | string | Exact data verification status, e.g. `verified` or `needs_review`. |
| band | very_good | good | regular | bad | insufficient_data | Keep only dog foods in this score band. |
| min_confidence | integer (0–100) | Minimum label data confidence (0-100). |
| products | string | Comma-separated product UUIDs (at most 25) to restrict the result to. |
List dog food brands
GET /api/foods/brands · operationId listDogFoodBrands
Up to 20 brands, alphabetical, that have at least one active dog food. Use the returned `id` with `listBrandDogFoods`.
| Parameter | Type | Meaning |
|---|
| q | string (max 50) | Keep only brands whose name contains this text (case-insensitive). |
List the dog foods of one brand
GET /api/foods/products · operationId listBrandDogFoods
Up to 20 active dog foods of a brand, alphabetical by product name.
| Parameter | Type | Meaning |
|---|
| brandId * | string (uuid) | Brand UUID from `listDogFoodBrands`. |
| q | string (max 50) | Keep only products whose name contains this text (case-insensitive). |
Example
curl 'https://petfoodfix.com/api/foods/products/search?q=royal+canin+medium+adult&market=uk'
HTTP/2 200
content-type: application/json
ratelimit-policy: "product-search";q=120;w=900
ratelimit: "product-search";r=119
{
"products": [
{
"id": "d6272886-81a4-432e-927d-51fe61acaf7b",
"brandName": "Royal Canin",
"productName": "Medium Adult Dry Dog Food",
"format": "dry",
"lifeStage": "adult",
"score": 67,
"band": "good",
"scoreRuleVersion": "food-score-v2.2.1",
"proteinPct": 25,
"fatPct": 14,
"kcal": 359.1,
"slug": "royal-canin-medium-adult-dry-dog-food",
...
}
],
"fuzzySuggestions": [],
"searchMethod": "combined",
...
}Body of a real response on 9 November 2026, shortened. Scores change when label data or the scoring rule version changes; always read scoreRuleVersion.
Errors
Every error is JSON with a human message in error, a stable code and, where it helps, a hint saying how to fix the request. Unknown /api paths return 404 with code: "not_found".
HTTP/2 400
content-type: application/json
{
"error": "Query too long",
"code": "query_too_long",
"hint": "Send q with at most 120 characters."
}Rate limits
Each endpoint allows 120 requests per 15 minutes per client IP (IPv6: per /64), counted separately. Responses carry the IETF RateLimit-Policy and RateLimit header fields (draft-ietf-httpapi-ratelimit-headers): q is the quota, w the window in seconds and r what is left. Over the limit you get 429 with Retry-After in seconds; wait that long before retrying. Cache what you fetch.
Machine-readable files
- /openapi.json — OpenAPI 3.1 contract of the endpoints above.
- /llms.txt — site summary and when-to-use guidance for language models.
- /index.md — the homepage as Markdown. The homepage also answers
Accept: text/markdown with it: curl -H 'Accept: text/markdown' https://petfoodfix.com/ - /sitemap.xml and /robots.txt.