Pet foods and recalls
The platform keeps one catalog of commercial pet foods: brands, products, the label of each product as printed (with a
history, because recipes change), the packages a product is sold in and the barcodes printed on them, and the recalls
that cover them. Everything below is an anonymous GET under pet-food/v1/. Responses use the standard envelope
(data, resultCode); properties whose value is null are left out. Codes (species DOG, life stage ADULT,
nutrient PROTEIN_G, allergen codes) are the platform’s shared vocabularies; names come in the locale you ask for,
with English as the fallback (Localized names).
What a particular pet eats is not part of the catalog; when its owner shows it publicly, it is read with Pet diet (public), whose items point back at the products and packages here.
Look up a barcode
Section titled “Look up a barcode”GET barcodes/{gtin} takes the digits printed under the barcode: UPC-A (12), EAN-13, EAN-8 or GTIN-14. A UPC-A and
the same code as EAN-13 or GTIN-14 find the same package.
| Answer | When | data |
|---|---|---|
200, resultCode PetFood_Barcode_GT_Resource_SU | The barcode belongs to a published package. | gtin, gtin14, variant (the package), product (a product summary), currentVersionId |
404, PetFood_Barcode_GT_Resource_FL | A valid barcode the catalog does not know. | gtin, isValidGtin: true, contribute: a message to show, and photoRoles / requiredPhotoRoles (FRONT, BACK, INGREDIENTS, ANALYSIS, BARCODE; front and ingredients required) describing how a signed-in member of the platform adds the food |
400, PetFood_Barcode_VL_Gtin_RJ | Not a barcode: wrong length, letters, or a wrong check digit. | none |
A package (variant) has id, name (“30 lb bag”), packQuantity + packUnitCode (g, kg, oz, lb, mL,
L, count), containerText, flavourText, isActive (still sold) and barcodes (gtin as printed, gtin14,
kindCode GTIN8 / GTIN12 / GTIN13 / GTIN14, countryCode, isPrimary).
Search products
Section titled “Search products”GET products?q=&species=&form=&claim=&lifeStage=&brand=&page=&pageSize= returns published, discontinued and recalled
products, sorted by name. q matches every word against the product name, the brand and other names the product is
sold under; a word of 8 to 14 digits also matches a barcode. brand takes a brand id or slug; form a food form code
(DRY, WET, …; GET lookups/food-forms); claim a dietary claim (GRAIN_FREE, …). pageSize defaults to 24,
up to 100.
A product summary carries id, slug, name, brandId, brandName, brandSlug, foodFormCode, speciesCodes,
lifeStageCodes, dietaryClaimCodes, statusCode (PUBLISHED, DISCONTINUED, RECALLED),
requiresVetAuthorization (a prescription diet: show it, do not block it), kcalPerKg, kcalPerCup,
energyIsDerived, frontMediaId and hasOpenRecall.
Read a product and its label
Section titled “Read a product and its label”GET products/{idOrSlug}?locale= returns the summary plus the adequacy statement (adequacyClaimCode,
adequacyMethodCode, adequacyStandardCode such as AAFCO, and adequacyStatementText as printed), the packages,
photos (media: mediaId + roleCode), content sections, external codes, other names, its recalls, and the label in
force today (currentVersion) with the list of all versions. A merged duplicate answers with the product it was
merged into, so a stored id keeps working.
A label version has versionNo, effectiveFrom / effectiveTo (dates), changeNote and:
| Part | Fields |
|---|---|
ingredients | In label order: position, labelText as printed, isSubIngredient + parentPosition for the parts printed in parentheses, ingredientId when linked to the platform’s ingredient list, allergenCodes, and safety (see below). |
analysis | One row per value: nutrientCode (or absent when the label’s line has no platform nutrient), labelName as printed, min / max / typical, unitCode (PCT, MG_PER_KG, IU_PER_KG, G_PER_MCAL, …), basisCode and isDerived. AS_FED rows are printed on the label; DRY_MATTER and PER_MCAL (per 1,000 kcal) rows are calculated from them and marked isDerived: true. |
energy | kcalPerKg, kcalPerCup, kcalPerUnit + unitLabel, method, isDerived (true when the label prints no calorie statement and the value is estimated from the analysis with modified Atwater factors). |
feedingGuide | speciesCode, lifeStageCode, weightFromKg / weightToKg, amountPerDay (+ amountPerDayMax), unitCode (cup_us, g, can, …), notes. |
allergenCodes | Every allergen of the linked ingredients. |
GET products/{idOrSlug}/versions/{versionNo} returns one past or current version: use it with a date you stored to
show the label a pet was actually fed.
Ingredient safety
Section titled “Ingredient safety”Each ingredient linked to the platform’s ingredient list carries safety: one entry per species the platform has a
verdict for, speciesCode (DOG, CAT, …), safetyLevel and an optional note. The array is empty when there is
no verdict or the label row is not linked (rows are linked only when the printed text is exactly a known ingredient
name, never by guessing).
safetyLevel | Meaning |
|---|---|
SAFE | Safe for that species. |
MODERATION | Fine in moderation. |
CAUTION | Use with caution. |
TOXIC | Toxic to that species. |
LETHAL | Can be fatal to that species. |
{ "position": 12, "labelText": "…", "ingredientId": "…", "allergenCodes": [], "safety": [ { "speciesCode": "CAT", "safetyLevel": "TOXIC", "note": "…" }, { "speciesCode": "DOG", "safetyLevel": "CAUTION" } ] }Show TOXIC and LETHAL prominently. A SAFE entry without a note adds nothing for most readers.
Where it is sold
Section titled “Where it is sold”commerceLinks on a product lists its packages that are sold in the United Pet Club store, one row per package:
variantId, catalogItemId, catalogItemPublicCode (the store product’s code) and ownerScopeCode (PLATFORM:
one store product per package, shared by every seller). A package that nobody has listed yet has no row. Link to the
store product by its code; offers and prices are not part of this API.
"commerceLinks": [ { "variantId": "49cca6fd-6c71-5da9-8021-b823720802ab", "catalogItemId": "01a12f8a-974c-713c-814e-6a9f4432add9", "catalogItemPublicCode": "UPC-CI-BXASWPVROP", "ownerScopeCode": "PLATFORM" }]Read one package
Section titled “Read one package”GET variants/{id} returns a package of a public product together with its product summary, for when you stored a
package id (from a barcode scan, a diet item or a recall scope):
{ "data": { "variant": { "id": "49cca6fd-6c71-5da9-8021-b823720802ab", "name": "15 lb bag", "packQuantity": 15.0, "packUnitCode": "lb", "containerText": "bag", "isActive": true, "barcodes": [ { "gtin": "038100101679", "gtin14": "00038100101679", "kindCode": "GTIN12", "countryCode": "US", "isPrimary": true } ] }, "product": { "id": "14d382e2-481f-53eb-b9d5-7baf8b7f04d0", "slug": "purina-pro-plan-adult-complete-essentials-…", "brandName": "Purina Pro Plan", "brandSlug": "purina-pro-plan", "foodFormCode": "DRY", "speciesCodes": ["DOG"], "statusCode": "PUBLISHED", "requiresVetAuthorization": false, "kcalPerKg": 3790.0, "hasOpenRecall": false } }, "resultCode": "PetFood_Catalog_GT_Resource_SU"}An unknown id, or a package whose product is not public, answers 404.
Brands and vocabularies
Section titled “Brands and vocabularies”-
GET brands?q=&sort=&page=&pageSize=lists brands (id,sysName,name,slug,manufacturerName,countryCode,websiteUrl,isPlaceholder,productCount), by name.sort=popularputs the brands with the most public products first. -
GET brands/{slug}returns one brand.profileIdis the brand’s business profile on United Pet Club, when it has one;claimedByProfileIdnames the business profile that claimed the brand.isPlaceholder: truemeans no business manages the brand yet.{ "data": { "id": "ccd243fd-e6eb-5052-9217-8bfa5206c459", "sysName": "PURINA_PRO_PLAN", "name": "Purina Pro Plan","slug": "purina-pro-plan", "manufacturerName": "Nestlé Purina PetCare", "countryCode": "US","websiteUrl": "https://www.purina.com", "isPlaceholder": true, "productCount": 6 },"resultCode": "PetFood_Catalog_GT_Resource_SU" } -
GET lookupslists the vocabulary sets;GET lookups/{set}?locale=returns one (code,name,description,sortOrder):food-forms,dietary-claims,adequacy-claims,adequacy-methods,analysis-bases,recall-reasons,recall-authorities,media-roles,life-stages,nutrients,allergens, and the status sets.
Recalls
Section titled “Recalls”GET recalls?species=&country=&since=&status=&page=&pageSize= lists published recalls, newest first. status is
OPEN (published or updated), CLOSED, or a single status; country keeps recalls announced for a country (ISO
3166-1 alpha-2: US, CA, GB); since keeps recalls announced on or after a date (2026-10-01). pageSize
defaults to 25.
GET recalls/{id} returns the recall: authorityCode (FDA, CFIA, FSA, MANUFACTURER, OTHER),
externalNumber, title, summary, classificationText, reasonKindCode / reasonText, speciesCodes,
countryCodes, announcedOn, sourceUrl (the official notice), statusCode, revision (1 when published, +1 per
update), and:
scopes: what it covers, one row each:scopeKindCodeBRAND,PRODUCT(every package) orVARIANT(one package), the brand / product / package ids and names, the affectedgtins,lotText,bestByFrom/bestByToandregionCodes.updates: its history (kindCode,note,revision,atUtc).
To warn your users, match the gtins (or package ids) of a recall’s scopes against the packages they use, then narrow
by lot and best-by date when the scope gives them. Always link to sourceUrl.