# The Beauty API: instructions for coding agents
Base URL: https://api.thebeautyapi.com/v1 (JSON over HTTPS)
Auth: send the header x-api-key: $BEAUTY_API_KEY on every /v1 request. Keep the key in an environment variable, never in code or in this file.
Reference: https://thebeautyapi.com/docs.md | Spec: https://api.thebeautyapi.com/openapi.json | Keys: https://thebeautyapi.com/dashboard

## Endpoints
- Health: GET /health (no key)
- Search products: GET /v1/products/search?q=&page=
- Filter products: GET /v1/products?category=&brand=&origin=&fragrance_free=&alcohol_free=&paraben_free=&sulfate_free=&silicone_free=&has_ingredient=&excludes_ingredient=&page=
- Get a product: GET /v1/products/{id}
- Barcode lookup: GET /v1/products/barcode/{barcode} (barcode plans only)
- Batch products: POST /v1/products/batch (body {"ids": [uuid, ...]}, max 50)
- Search ingredients: GET /v1/ingredients/search?q=&page=
- Get an ingredient: GET /v1/ingredients/{id}

## Rules
1. Find a product with search, then fetch the full record with GET /v1/products/{id}. Search and filter return slim records (id, brand, name, category, image_url); detail, batch and barcode return the full record with the ingredient list in on-label order.
2. Every word in q must appear in the product's brand or name, in any order. Send the brand plus the distinctive part of the name ("CeraVe Moisturizing Cream"), never a full retail title. Case, accents and punctuation are ignored; the last word may be partial.
3. When pagination.total is 0 the response carries a no_match object: drop the word no_match.hint names and retry. An empty result does not mean the brand is missing.
4. Pages hold 20 results; page runs 1 to 51 and anything higher returns 400. Read pagination.total and pagination.has_more; above 1,020 matches, narrow with filters instead of paging.
5. Batch takes up to 50 ids and is billed per item (50 ids = 50 calls); unknown ids come back as null in the same positions.
6. Errors are JSON {statusCode, error, message} and message says what to change. 403 is a missing or revoked key, or a plan without barcode lookup. 429 is the rate limit; no rate-limit headers are sent, so back off exponentially.
7. Barcodes are a lookup key, not a field: no response lists a product's codes. image_url can be null.
