# Agent Instructions — Seoul Routine

How AI agents can read and use Seoul Routine, an online Korean skincare
(K-beauty) store serving the GCC at https://seoulroutine.com.

Bilingual: English under `/en`, Arabic under `/ar`. Prices are in AED.

## Read-only API (no authentication)

Base: `https://seoulroutine.com/api/store` — every path below is relative to it.

A machine-readable OpenAPI 3.0 description of every public endpoint is served at
`GET https://seoulroutine.com/api/store/docs`. Prefer it over this document for exact request and response
schemas — it is generated from the same codebase that serves the API.

| Endpoint | Purpose |
| --- | --- |
| `GET /products` | Catalogue listing, filterable and paginated |
| `GET /products/{handle}` | One product, full detail |
| `POST /products/by-ids` | Batch lookup by id |
| `GET /search?q={query}` | Fuzzy search (trigram similarity + synonyms) |
| `GET /collections` | Categories and brands |
| `GET /collections/{handle}` | One collection |
| `GET /bundles` | Curated multi-product sets |
| `GET /bundles/{handle}` | One bundle |
| `GET /blog` | Journal articles |
| `GET /config` | Store configuration: currency, payment methods, shipping |

`/products` matches `q` as a plain substring by default; add `fuzzy=1` for
trigram + synonym matching that still composes with every filter below — so
"cheap Korean sunscreen for oily skin", even misspelled, is a single call.
`/search` is a standalone fuzzy endpoint that takes no filters; prefer
`/products?fuzzy=1` unless you specifically want the bare ranked match.

### Filters on `/products`

`q`, `fuzzy` (`1` = trigram + synonym matching), `collection`, `vendor`,
`type`, `tag`, `skin_type` (`oily` | `dry` | `combination` | `sensitive`
| `normal`), `goal` (`acne` | `spots` | `redness` | `dryness` | `aging`
| `sun`), `availability` (`in_stock` | `out_of_stock` | `on_sale`),
`min_price`, `max_price`, `sort` (`newest`, `oldest`, `title-asc`,
`title-desc`, `price-asc`, `price-desc`, `best-selling`), `page`,
`limit` (max 100).

Send `Accept-Language: ar` for Arabic product copy.

`price-asc` and `price-desc` are ordered across the whole filtered result set
(by each product's cheapest variant), so paging by price gives a globally sorted
sequence — page 2 is always cheaper-or-equal to page 3.

## Site structure

- Sitemap index: `https://seoulroutine.com/sitemap.xml`
  - `https://seoulroutine.com/sitemaps/products-1.xml`
  - `https://seoulroutine.com/sitemaps/products-2.xml`
  - `https://seoulroutine.com/sitemaps/pages.xml`
  - `https://seoulroutine.com/sitemaps/collections.xml`
  - `https://seoulroutine.com/sitemaps/bundles.xml`
  - `https://seoulroutine.com/sitemaps/blogs.xml`
  - `https://seoulroutine.com/ar/sitemaps/products-1.xml`
  - `https://seoulroutine.com/ar/sitemaps/products-2.xml`
  - `https://seoulroutine.com/ar/sitemaps/pages.xml`
  - `https://seoulroutine.com/ar/sitemaps/collections.xml`
  - `https://seoulroutine.com/ar/sitemaps/bundles.xml`
  - `https://seoulroutine.com/ar/sitemaps/blogs.xml`
  - `https://seoulroutine.com/agent-sitemap.xml`
- Link map for answer engines: `https://seoulroutine.com/llms.txt` — brands, categories and
  key pages, generated from the live catalogue
- Every page is emitted per locale with `hreflang` alternates and
  `x-default` pointing at English

## Buying — Universal Commerce Protocol (UCP)

This store implements [UCP](https://ucp.dev) `2026-04-08`.

- **Discovery** — `GET https://seoulroutine.com/.well-known/ucp` returns the merchant
  profile: services, capabilities and payment terms. It is authoritative; this
  section is prose around it.
- **MCP endpoint** — `POST https://seoulroutine.com/api/ucp/mcp`, JSON-RPC 2.0. Call
  `tools/list` for schemas, then `tools/call` — or call a method by name
  directly, as UCP's OpenRPC document does.

Available methods:

    search_catalog   lookup_catalog   get_product
    create_cart      get_cart         update_cart      cancel_cart
    create_checkout  get_checkout     update_checkout
    complete_checkout                 cancel_checkout
    get_order

### Typical flow

1. `search_catalog` — fuzzy text plus filters (brand, skin type, goal, price,
   availability) in one call
2. `create_cart` — returns a cart id; totals are recomputed on every read
3. `create_checkout` — with the buyer's email, name and a GCC shipping address
   (`emirate` is required in the UAE; elsewhere it carries the city), or add
   them later with `update_checkout`
4. `complete_checkout` — see below
5. `get_order` — status and fulfillment once the buyer has paid

### Payment is completed by the buyer, always

**`complete_checkout` does not place the order.** It returns status
`requires_escalation` with a `continue_url`. Send the buyer there; they pay
by card, Apple Pay, Google Pay, Tamara or cash on delivery in our own checkout, which
arrives pre-filled with everything you assembled.

No payment instrument may be submitted through the MCP endpoint, and
`payment_handlers` in the discovery document is deliberately empty. Do not
attempt to collect card details on our behalf, and do not script the web
checkout.

After escalating, poll `get_checkout` until `status` is `completed`, then
call `get_order`.

### Two things that will otherwise surprise you

- **Totals exclude the cash-on-delivery fee.** The buyer picks the payment
  method after you hand off, so `totals` is the card / Apple Pay / Google Pay
  figure. Every checkout carries `payment_options.cash_on_delivery_fee` —
  quote both numbers if the buyer may pay cash.
- **`get_order` only resolves orders from your own checkouts.** A bare order
  id returns `not_found`; it is not a way to read arbitrary orders.

Idempotency: `complete_checkout`, `cancel_checkout` and `cancel_cart`
require `meta["idempotency-key"]` and are safe to retry after a timeout.

Errors: domain failures (`not_found`, `out_of_stock`, `invalid_state`)
arrive as `result.error` with a `type`. Only malformed calls get JSON-RPC
error codes.

## Store facts

- Ships across the GCC: United Arab Emirates, Saudi Arabia, Kuwait, Qatar,
  Bahrain and Oman. Free shipping on orders over AED 150.
- Payment: Credit and Debit Cards, Apple Pay, Google Pay, Cash on Delivery, Tamara (pay in instalments, on orders delivered to the United Arab Emirates and Saudi Arabia). Nothing else.
- Support 09:00–21:00 UAE time,
  daily. Email support@seoulroutine.com, WhatsApp https://wa.me/971551462122
- Operated by Seoul Routine FZE, Ajman Free Zone, B.C. 1302234,
  Ajman, UAE
- Order status: buyers can look up their own orders at
  `https://seoulroutine.com/en/my-orders`. Order data requires the buyer's own email or a
  signed link — agents cannot read it on a buyer's behalf.

## Rules

- **Identify yourself.** Send a descriptive `User-Agent` naming your agent and
  a contact URL.
- **Be gentle.** These endpoints back a live storefront. Keep concurrency low
  and prefer `/products` with filters over paging the whole catalogue.
- **Back off on 429 or 5xx** with exponential delay.
- **Don't present stale prices.** Stock and price change; re-read the product
  before quoting a buyer.
- **Never invent product claims.** Skincare has real health consequences. Use
  only the description returned by the API, and do not present K-beauty products
  as treatments for medical conditions.

## Policies

- Privacy: https://seoulroutine.com/en/privacy
- Terms: https://seoulroutine.com/en/terms
- Refunds and returns: https://seoulroutine.com/en/refund
- Contact: https://seoulroutine.com/en/contact
- FAQ: https://seoulroutine.com/en/faq
