# Casafari API and MCP Platform auth.md

You are an agent. This document tells you how to obtain a credential for Casafari's property data on the platform at https://platform.casafari.com. Follow the steps for the path you need, in order.

## Who this is for

A credential acts for a **person who holds a Casafari account**. It grants nothing on its own: the account's plan, tokens and products decide what a call may do. The person, never you, accepts the Terms of Use, and the person receives every code and every payment link. If there is no person to ask, stop: no path below works without one.

Pick one path:

- **Sign-up API**: you have the person's email and want an API key. Works for REST and MCP.
- **OAuth**: you are an MCP client (or any OAuth client) and the person can open a browser.
- **Unattended**: the person already has an account and creates a key or a confidential client for you in the console.

## Sign-up API

1. `GET https://platform.casafari.com/v1/signups/terms` returns `terms_version`, `terms_url` and `privacy_url`. Show the person both links.
2. `POST https://platform.casafari.com/v1/signups` with `{"email": "<the person's email>", "terms_version": "<from step 1>", "client": {"name": "<your name>"}}` answers `202` with `signup_id`. Casafari emails the person a 6-digit code that names your client and says that giving the code accepts the Terms and opens the account.
3. Ask the person for the code. Do not guess it: each wrong code uses one of a few attempts.
4. `POST https://platform.casafari.com/v1/signups/{signup_id}/verify` with `{"code": "<6 digits>"}` answers `201` with `api_key` (shown once: store it as a secret), `scopes` and `plan`. A new account starts on the Free plan: 1,000 tokens for 30 days. An email that already has an account gets a new key on that account instead, with no second trial.

Errors: [`terms_not_accepted`](https://platform.casafari.com/errors/terms-not-accepted) (send the current `terms_version`), [`email_not_allowed`](https://platform.casafari.com/errors/email-not-allowed), [`verification_code_invalid`](https://platform.casafari.com/errors/verification-code-invalid) (`attempts_remaining`), [`verification_code_expired`](https://platform.casafari.com/errors/verification-code-expired) (start again), [`signup_limited`](https://platform.casafari.com/errors/signup-limited).

## OAuth

One authorization server, many protected resources. Each resource is a separate audience: a token works on the one resource it was issued for.

1. **Discover.** Call the resource without a token. It answers `401` with `WWW-Authenticate: Bearer resource_metadata="..."`. For example `https://platform.casafari.com/mcp/locations` points to `https://platform.casafari.com/.well-known/oauth-protected-resource/mcp/locations`. Read `resource`, `authorization_servers` and `scopes_supported` there, then `https://platform.casafari.com/.well-known/oauth-authorization-server`.
2. **Register.** Use your Client ID Metadata Document URL as `client_id` (preferred), or register at `https://platform.casafari.com/oauth/register` (RFC 7591): a public client (`token_endpoint_auth_method: "none"`), `https` or loopback redirect URIs, grant types `authorization_code` and `refresh_token`. Registration carries no identity and gives you no access: `agent_auth.identity_types_supported` is `["anonymous"]`.
3. **Let the person claim it.** Open `https://platform.casafari.com/oauth/authorize` in the person's browser with `response_type=code`, `client_id`, `redirect_uri`, `state`, `code_challenge` and `code_challenge_method=S256`, and `resource` set to the resource's `resource` value. `scope` is optional (default: every scope of that resource). The person signs in, or signs up there and accepts the Terms, then chooses an account and allows your client.
4. **Exchange the code.** `POST https://platform.casafari.com/oauth/token` with `grant_type=authorization_code`, `code`, `redirect_uri`, `client_id` and `code_verifier`. You get an access token (`expires_in`: 900 seconds) and a refresh token.
5. **Refresh.** `grant_type=refresh_token` returns a new pair every time; keep only the newest. Presenting a used refresh token again after 30 seconds revokes the whole grant, and the person has to allow your client again.
6. **Revoke.** `POST https://platform.casafari.com/oauth/revoke` with the token and your `client_id` ends the grant.

For another resource, run steps 3 and 4 again with its `resource`: one account, separate tokens.

## Unattended

A client you registered yourself cannot use `client_credentials`. For a job that runs without a person, the person creates an API key, or a confidential client (`client_credentials` with a secret, shown once), in the console at https://platform.casafari.com/console and gives it to you.

## Using a credential

- API key: `Authorization: Bearer cf_sk_...` or `X-API-Key: cf_sk_...`, on REST and MCP alike. Never in a URL: a key in a query string is refused and should be revoked.
- Access token: `Authorization: Bearer <token>`, only on the resource it was issued for.
- Every credential can read its own account (`account:read`) and look up place ids (`locations:read`); other scopes follow the products the account is entitled to.

## Errors you will meet

- `401` [`invalid_credential`](https://platform.casafari.com/errors/invalid-credential): missing, revoked or expired. Refresh a token; for a key, ask the person.
- `402` [`payment_required`](https://platform.casafari.com/errors/payment-required): the tokens ran out. Give the person `upgrade_url`, then poll `GET https://platform.casafari.com/v1/account/payment-links/{payment_link_id}` about every 5 seconds until `status` is `completed`, and retry.
- `403` [`not_entitled`](https://platform.casafari.com/errors/not-entitled) or [`insufficient_scope`](https://platform.casafari.com/errors/insufficient-scope): the account's plan or the credential's scopes do not cover the call.
- `429` [`request_limit_reached`](https://platform.casafari.com/errors/request-limit-reached) or [`rate_limited`](https://platform.casafari.com/errors/rate-limited): wait for `Retry-After`.

Every error is `application/problem+json`; its `type` URI is a page explaining the code.

## More

- How to call each product: https://platform.casafari.com/llms.txt
- API catalog: https://platform.casafari.com/.well-known/api-catalog
- Documentation: https://developers.casafari.com/docs/authentication
