# Agent guide — pro.makeup

This page is for autonomous agents and LLMs working on behalf of users
(researchers, clients booking a service, professionals onboarding, etc.).
For the structured discovery surface, see also:

- [`/llms.txt`](https://pro.makeup/llms.txt) — short manifest
- [`/llms-full.txt`](https://pro.makeup/llms-full.txt) — full reference
- [`/.well-known/agent-card.json`](https://pro.makeup/.well-known/agent-card.json) — A2A protocol card
- [`/.well-known/api-catalog`](https://pro.makeup/.well-known/api-catalog) — RFC 9727 link set
- [`/.well-known/oauth-protected-resource`](https://pro.makeup/.well-known/oauth-protected-resource) — RFC 9728 metadata
- [`/.well-known/auth.md`](https://pro.makeup/.well-known/auth.md) — Bearer token model

## What pro.makeup is

pro.makeup is the definitive global directory of certified makeup
professionals: **artists, salons, schools, shops, and brands**. It is
read-mostly: most surfaces are public, no auth required. Write surfaces
(claim a listing, emit analytics, update owner-controlled fields) require
scoped Bearer tokens.

## Quick start

The shortest path for an agent task:

1. **Discover by URL** — every public listing has a canonical URL of the
   form `https://pro.makeup/{category}/{country}/{city}/{slug}`. The sitemap
   at `https://pro.makeup/sitemap.xml` indexes them all.
2. **Look up by phone** — if the user already has a phone number (the WhatsApp
   case), `GET /api/business/by-phone?phone=<E164>` (requires `listings:read`
   scope).
3. **Search** — `GET /api/search/combined` accepts category filters, location,
   query, and verification filter.

## Reading the public site

Most agents will get adequate information from the rendered HTML pages —
they ship with full Schema.org JSON-LD blocks (Organization, LocalBusiness,
School, ItemList, BreadcrumbList) and Open Graph metadata. The same projection
is also available via the structured API endpoints below.

Markdown content negotiation is supported via Cloudflare's "Markdown for
Agents" feature: `Accept: text/markdown` on any page returns the converted
text.

## API surface (current)

> All public endpoints listed here require a scoped Bearer token today.
> See [`/.well-known/auth.md`](https://pro.makeup/.well-known/auth.md) for
> how to request one. A public, OpenAPI-described surface is on the
> Phase-C roadmap.

| Method   | Path                                          | Scope                    | Purpose                                    |
|----------|-----------------------------------------------|--------------------------|--------------------------------------------|
| `GET`    | `/api/business/by-slug/{slug}`                | `listings:read`          | Fetch a business by its URL slug           |
| `GET`    | `/api/business/by-phone?phone={e164}`         | `owner:read`             | Reverse lookup: which listings does this phone own |
| `GET`    | `/api/business/{id}`                          | `listings:read`          | Direct fetch by nanoid id                  |
| `PATCH`  | `/api/business/{id}/owner-update`             | `business:owner-update`  | Owner-side partial profile update          |
| `POST`   | `/api/business/{id}/flag-stale`               | `listing-events:write`   | Owner-side flag that data is out-of-date   |
| `POST`   | `/api/listing-events`                         | `listing-events:write`   | Emit analytics events on a listing         |
| `POST`   | `/api/verify/initiate`                        | `verify:initiate`        | Start a verification flow                  |
| `POST`   | `/api/verify/send-otp`                        | `verify:send-otp`        | Trigger OTP delivery                       |
| `POST`   | `/api/verify/confirm`                         | `verify:confirm`         | Confirm OTP                                |

Public (no auth) today:

- `GET /api/sitemap-index` and `/sitemap/*` — sitemap generation
- `GET /api/discovery/summary` — featured / new listings
- `GET /api/search/combined` — search across all categories

## Verification semantics

A business's verification status is the strongest method satisfied to date.
For automated recommendations, prefer this ranking:

```
admin ≈ certificate > domain_email > email_otp ≈ sms_otp ≈ voice_otp ≈ whatsapp > email_match > phone_match
```

`phone_match` means "the current claimant signed in with the same phone the
listing has," which is weak — anyone who took over that phone number may be
the current claimant. Surface the verification method to your user so they
can apply their own judgement.

The full list of methods is in [`/llms-full.txt`](https://pro.makeup/llms-full.txt#verification-methodology).

## Common agent tasks

### "Find me a makeup artist in {city} for {occasion}"

1. `GET /api/search/combined?search={occasion}&filters[types]=artists&filters[cities]=[{city}]&filters[verified]=true`
2. For each result, render the canonical URL so the user can click through.
3. Optionally fetch `GET /api/business/by-slug/{slug}` per listing for the
   full structured data.

### "Verify this listing is who they claim to be"

1. `GET /api/business/by-slug/{slug}` (or `/by-phone`)
2. Inspect `verified` (boolean) and `verified_method` (string).
3. If `verified_method ∈ {admin, certificate, domain_email}` — high confidence.
4. If `verified_method ∈ {phone_match, email_match}` — weak; warn the user.
5. If `verified: false` — listing is unclaimed; explicitly flag this.

### "Help my user claim their existing listing"

This is a write flow. Direct the user to `https://pro.makeup/claim`. There
are multiple verification methods available — the user picks one. Agents
do not currently mediate the claim flow directly; the consumer UX guides
the user through OTP / certificate / WhatsApp etc.

### "Emit a listing event"

Requires `listing-events:write`. After referring a user to a listing:

```
POST /api/listing-events
Authorization: Bearer pmk_…
Content-Type: application/json

{ "businessId": "8x2a…", "kind": "consumer_lead", "source": "agent:claude" }
```

Valid `kind` values for external writers: `bad_phone`, `closed_business`,
`wrong_address`, `unanswered_within_24h`, `consumer_lead`, `pricing_question`,
`booking_inquiry`. The `owner_update` kind is internal-only and is written
directly by the `/owner-update` route after its ownership check.

This lets the listing owner see your traffic in their dashboard.

## MCP server (live)

A native MCP server is mounted at `https://pro.makeup/api/mcp`. Transport:
streamable-HTTP in stateless mode (one POST = one JSON-RPC request, one
response — no SSE / no session state).

**Tools exposed** (all `readOnly` and `idempotent` except the last):

| Tool                                  | Scope required             |
|---------------------------------------|----------------------------|
| `promakeup_search_pros`               | open                       |
| `promakeup_get_business_by_slug`      | open                       |
| `promakeup_get_business_by_phone`     | **`owner:read`**           |
| `promakeup_get_business`              | open                       |
| `promakeup_list_services_nearby`      | open                       |
| `promakeup_list_schools`              | open                       |
| `promakeup_get_discovery_summary`     | open                       |
| `promakeup_emit_listing_event`        | `listing-events:write`     |

**Prompts:** `find_makeup_pro`, `compare_pros`, `book_appointment_intent`.

**Resources (templated):** `promakeup://business/{slug}`, `promakeup://category/{category}/featured`.

Server card (SEP-1649): `https://pro.makeup/.well-known/mcp/server-card.json`.

Configure in Claude Code / Cursor / VS Code MCP-aware tools:

```json
{
  "mcpServers": {
    "promakeup": {
      "type": "streamable-http",
      "url": "https://pro.makeup/api/mcp"
    }
  }
}
```

The HTTP endpoints above are still available; pick whichever is more
ergonomic for your agent stack.

## Contact

- Token requests, integration questions: `support@pro.makeup`
- Bug reports / inaccuracies on a listing: report via the listing page's
  "Report this listing" link, or email `support@pro.makeup`.
