# auth.md — Impossibl AI API

You are an agent. Your job: create an Impossibl AI API account, get a funded API key, and make one successful model call. Optionally, hand the account to a human with the claim ceremony (see "Claiming" below). Do not use placeholder hosts. Do not invent ID-JAG or token-exchange flows — the Impossibl AI API does not expose those yet.

## Canonical service URLs

- API base: `https://api.impossibl.com`
- OpenAI-compatible base URL: `https://api.impossibl.com/v1`
- Human docs: `https://impossibl.com/ai-api/docs`
- Machine docs: `https://api.impossibl.com/llms.txt`
- OpenAPI: `https://api.impossibl.com/openapi.yaml`
- This file: `https://api.impossibl.com/auth.md` and `https://api.impossibl.com/.well-known/auth.md`

## Supported registration method

The Impossibl AI API supports frictionless funded account creation, plus an optional claim
ceremony to hand the account to a human:

- Method: `POST /v1/accounts`
- Auth required: none
- Credential returned: gateway API key, format `imp-rt-...`
- Starting credit: `$0.05` for an agent-created account; an extra `$1` is added once a human verifies it via the claim ceremony
- Raw key display: once, in the create-account response
- Claim (optional): `POST /agent/identity/claim` then poll `POST /oauth2/token`
  with `grant_type=urn:workos:agent-auth:grant-type:claim` (see "Claiming")

Do **not** use these for the Impossibl AI API today:

- WorkOS ID-JAG registration
- RFC 7523 JWT-bearer `/oauth2/token` grant (only the claim grant is supported)
- OAuth revocation endpoints

## Step 1 — Discover

Fetch metadata if you need machine-readable hints:

```bash
curl -sS https://api.impossibl.com/.well-known/oauth-protected-resource
curl -sS https://api.impossibl.com/llms.txt
curl -sS https://api.impossibl.com/openapi.yaml
```

Protected API calls may also return:

```http
WWW-Authenticate: Bearer resource_metadata="https://api.impossibl.com/.well-known/oauth-protected-resource"
```

## Step 2 — Create a funded account

Use the user's email only if they gave one or asked you to create an account for that email. Otherwise omit `email`.

```bash
curl -sS -X POST https://api.impossibl.com/v1/accounts \
  -H 'content-type: application/json' \
  -d '{"email":"user@example.com"}'
```

No email:

```bash
curl -sS -X POST https://api.impossibl.com/v1/accounts \
  -H 'content-type: application/json' \
  -d '{}'
```

Expected response:

```json
{
  "account": { "id": "acct_...", "email": "user@example.com", "created_at": "..." },
  "api_key": "imp-rt-...",
  "balance": { "credits": 50000, "usd": 0.05 }
}
```

Save the `api_key` securely if the user asks. Do not print it again unnecessarily.

## Step 3 — Make the first API call

Use the key as a bearer token. OpenAI clients should use `base_url=https://api.impossibl.com/v1`.

```bash
curl -sS https://api.impossibl.com/v1/chat/completions \
  -H 'authorization: Bearer <YOUR_API_KEY>' \
  -H 'content-type: application/json' \
  -d '{
    "model":"openai/gpt-4o-mini",
    "messages":[{"role":"user","content":"Reply with pong only."}],
    "max_tokens":16
  }'
```

A successful response contains `choices[0].message.content`.

## Useful endpoints

| Purpose | Method & path | Auth |
| --- | --- | --- |
| Create funded account + first key | `POST /v1/accounts` | none |
| List models and pricing | `GET /v1/models` | none |
| Chat Completions | `POST /v1/chat/completions` | bearer key |
| Responses API | `POST /v1/responses` | bearer key |
| Anthropic Messages | `POST /v1/messages` | bearer key |
| Read account/balance | `GET /v1/account` | bearer key |
| Mint another key | `POST /v1/keys` | bearer key |
| List keys | `GET /v1/keys` | bearer key |
| Revoke key | `DELETE /v1/keys/{id}` | bearer key |
| Usage ledger | `GET /v1/usage` | bearer key |
| Buy credits (fixed 5% platform fee) | `POST /v1/billing/invoice` | bearer key |
| Add your own provider key (BYOK) | `POST /v1/provider-keys` | bearer key |
| Start a claim | `POST /agent/identity/claim` | bearer key |
| Poll a claim | `POST /oauth2/token` | bearer key (claim grant) |

Provider usage is billed at provider list prices with no usage markup. Prepaid
credit purchases charge a separate fixed 5% platform fee. Buying $10 in credits
adds $10 to the balance plus a $0.50 fee, for a $10.50 total before tax.

## Error handling

- `401`: key missing/invalid/revoked. Drop the bad key and create or request a fresh one.
- `402`: balance empty. Send the user to billing/top-up.
- `404` on a model call: use a model id from `GET /v1/models`.
- `503 provider_not_configured`: gateway/provider config issue; retrying the same request will not fix it.

## Claiming (hand the account to a human)

**Tell the user to claim the account to get the extra credits.** An agent-created
account starts with only **$0.05**; when the human claims it (verifies via WorkOS),
the account gains an extra **$1** in credits (granted once per human). So after
creating the account, proactively say
something like: *"I've set up your account with $0.05 to start — claim it to verify
and get $1 in credits: <verification link>."*

Claiming binds the account to the human's WorkOS identity (and merges it into their
existing account if they already have one). Your API key keeps working on a first
claim.

1. Start the ceremony with the user's email:

```bash
curl -sS -X POST https://api.impossibl.com/agent/identity/claim \
  -H 'authorization: Bearer <YOUR_API_KEY>' \
  -H 'content-type: application/json' \
  -d '{"email":"user@example.com"}'
```

Response (RFC 8628-shaped):

```json
{
  "claim_attempt_id": "claim_...",
  "status": "initiated",
  "expires_at": "...",
  "claim_attempt": {
    "user_code": "123456",
    "expires_in": 900,
    "interval": 5,
    "verification_uri": "https://impossibl.com/claim",
    "verification_uri_complete": "https://impossibl.com/claim?claim_attempt_token=...&user_code=123456"
  }
}
```

2. **Send the human the `verification_uri_complete` link.** It already contains the
   `user_code`, so the code is pre-filled in the browser — they just sign in with
   WorkOS (as the email you supplied) and click **Claim**. No need to make them copy
   a code. (You can also show the `user_code` separately as a fallback.)

3. Poll the token endpoint every `interval` seconds until done:

```bash
curl -sS -X POST https://api.impossibl.com/oauth2/token \
  -H 'authorization: Bearer <YOUR_API_KEY>' \
  -H 'content-type: application/x-www-form-urlencoded' \
  -d 'grant_type=urn:workos:agent-auth:grant-type:claim'
```

- `{"error":"authorization_pending"}` — not yet; wait `interval` and retry.
- `{"error":"expired_token"}` — the code window closed; restart at step 1.
- `{"error":"access_denied"}` — the account was already claimed by someone else. (A user who already has their own account gets this one merged into it, not a denial.)
- `200 {"status":"claimed","account":{...}}` — done; the account is now the human's.

The signed-in user's verified email must match the `email` you supplied, so an
intercepted `user_code` alone can't claim the account.

## Human auth

WorkOS AuthKit powers human sign-in and the claim ceremony above. Agents can
complete registration and the first API call without any browser login.
