# makeup.land — V1 API quickstart > Focused index of the V1 REST API. For the full handbook (rewards > model, dual-tender pricing, semantic search internals, error > envelopes, etc.) see [/llms-full.txt](https://makeup.land/llms-full.txt). > The canonical machine-readable description is the OpenAPI spec. ## Discovery surfaces - [OpenAPI 3.1 (JSON)](https://makeup.land/openapi.json) — canonical - [OpenAPI 3.1 (YAML)](https://makeup.land/openapi.yaml) — mirror - [auth.md](https://makeup.land/auth.md) — token acquisition flow - [Protected Resource Metadata (RFC 9728)](https://makeup.land/.well-known/oauth-protected-resource) - [Authorization Server Metadata (RFC 8414)](https://makeup.land/.well-known/oauth-authorization-server) ## Base URL `https://makeup.land/api/v1` ## Authentication - **Bearer token** for most endpoints: `Authorization: Bearer ml_` - Tokens are issued manually — write to `shop@makeup.land` - Scopes: `full` (default), `register`, `giftcards`, `proposals` - Optional `read_only` flag on a token rejects every write with 403 - **Bearer + phone-keyed** for cart / payment-links / gift-cards-list / best-deals / opportunities: bearer token AS WELL AS `?phone=+972...` (E.164). Bearer authenticates the caller; phone selects the customer whose resources are returned. Phone in the body for POST/PATCH cart mutations, in `?phone=` query for GET/DELETE. - **Anonymous catalog browse** for `/api/v1/products` with tag / brand / near_hex / hue_family / sort filters — no bearer required. Bearer becomes mandatory once you pass `phone=`, `include=inventory`, or `relevant_to_phone=` (those return PII-keyed data). - **Public**: `/api/v1/gift-cards/validate` only — gated on code knowledge. ## Endpoint inventory | Method | Path | operationId | |--------|------|-------------| | GET | /api/v1/products | listProducts | | GET | /api/v1/brands | listBrands | | GET | /api/v1/customers | getCustomer | | POST | /api/v1/customers | upsertCustomer | | PATCH | /api/v1/customers/{id}/tags | patchCustomerTags | | GET | /api/v1/customers/{phone}/opportunities | listCustomerOpportunities | | GET | /api/v1/customers/best-deals | getCustomerBestDeals | | GET | /api/v1/cart | getCart | | DELETE | /api/v1/cart | clearCart | | POST | /api/v1/cart/items | addCartItem | | PATCH | /api/v1/cart/items/{lineItemId} | patchCartItem | | DELETE | /api/v1/cart/items/{lineItemId} | deleteCartItem | | GET | /api/v1/orders | listOrders | | GET | /api/v1/gift-cards | listGiftCards | | GET | /api/v1/gift-cards/validate | validateGiftCard | | POST | /api/v1/gift-cards/redeem | redeemGiftCard | | GET | /api/v1/payment-links | listPaymentLinks | | POST | /api/v1/register | registerCustomer | | GET | /api/v1/registrations | listRegistrations | | GET | /api/v1/registrations/{id} | getRegistration | | POST | /api/v1/proposals | submitProposals | ## Quickstart ```bash # Catalog read (no auth, tag-only) curl -s "https://makeup.land/api/v1/products?tag=lipstick&limit=5" # Search by shade (auth required) curl -s "https://makeup.land/api/v1/products?near_hex=%23C2185B&limit=5" \ -H "Authorization: Bearer ml_..." # Customer lookup curl -s "https://makeup.land/api/v1/customers?phone=%2B972501234567" \ -H "Authorization: Bearer ml_..." # Add cart item (bearer + phone in body, idempotent) curl -s -X POST "https://makeup.land/api/v1/cart/items" \ -H "Authorization: Bearer ml_..." \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{"phone":"+972501234567","product_id":"prod_x","variant_id":"var_y","quantity":1,"tender":"ils"}' ``` ## Error envelope Every error returns: ```json { "error": "human-readable", "error_code": "machine_readable_enum_value" } ``` Branch on `error_code`. Stable codes documented in the OpenAPI `components.schemas.Error` enum — 20 values including `invalid_quantity`, `tender_unavailable`, `insufficient_stock`, `customer_not_found`, `line_collision`, `rate_limited`, ... ## Idempotency All POST / PATCH / DELETE accept `Idempotency-Key` — a UUIDv4 per logical operation. Retries with the same key within 24h replay the original response.