# Generative Icons auth.md

You are an agent. Nothing here needs credentials: every endpoint is public and read-only, and requests without an `Authorization` header always work. Registering is optional. It gives your agent its own rate limit, 600 requests a minute, instead of the 120 a minute shared by everyone on your IP address.

Audience: AI agents, and the developers who build them, that use the Generative Icons API, MCP servers and A2A agent.

| Resource | URL |
| --- | --- |
| MCP server (icons) | https://generativeicons.com/mcp |
| MCP server (guides) | https://generativeicons.com/mcp/docs |
| A2A agent | https://generativeicons.com/a2a (card: https://generativeicons.com/.well-known/agent-card.json) |
| REST API | https://generativeicons.com/api/v1/ (described at https://generativeicons.com/openapi.json) |
| Files (never limited by credentials) | https://generativeicons.com/catalog.json, https://generativeicons.com/assets/<id>.lottie, https://generativeicons.com/docs/<slug>.md |

## Step 1: Discover

- Protected resource metadata (RFC 9728): https://generativeicons.com/.well-known/oauth-protected-resource
- Authorization server metadata (RFC 8414), with the `agent_auth` block: https://generativeicons.com/.well-known/oauth-authorization-server
- Signing keys: https://generativeicons.com/.well-known/jwks.json

## Step 2: Pick a method

- **anonymous**: the only method. There is no user identity to assert, so there is no consent step and no claim ceremony: there is no account to own, and nothing is kept about your agent.
- `identity_assertion` (ID-JAG) and `service_auth` are not offered; they answer `identity_assertion_not_enabled` and `service_auth_not_enabled`.

## Step 3: Register

```http
POST https://generativeicons.com/agent/identity
Content-Type: application/json

{ "type": "anonymous" }
```

Response (200):

```json
{
  "registration_id": "reg_...",
  "registration_type": "anonymous",
  "identity_assertion": "<service-signed JWT>",
  "assertion_expires": "<30 days from now>",
  "pre_claim_scopes": ["icons.read"],
  "token_endpoint": "https://generativeicons.com/oauth2/token"
}
```

Keep `identity_assertion` for its 30 days; register again after that.

## Step 4: Exchange the assertion

```http
POST https://generativeicons.com/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=<identity_assertion>
```

Response (200): `{"access_token": "<JWT>", "token_type": "Bearer", "expires_in": 3600, "scope": "icons.read"}`. The only scope, `icons.read`, covers everything the API, MCP servers and A2A agent offer.

## Step 5: Call

Send `Authorization: Bearer <access_token>` to the API, either MCP server or the A2A agent. Responses carry `RateLimit-Policy: "agent";q=600;w=60`.

```sh
curl -H "Authorization: Bearer $TOKEN" 'https://generativeicons.com/api/v1/icons?q=upload+failed&limit=3'
```

## Step 6: Refresh, and when a token is refused

- An access token lasts an hour: exchange the same assertion again (Step 4).
- `401` with `WWW-Authenticate: Bearer error="invalid_token"` means the token expired or was altered, or the signing key changed: exchange or register again, or drop the header (anonymous requests keep working). Only this site's tokens are checked; an `Authorization` header with anything else is ignored.
- There is no revocation endpoint: access tokens are short-lived and nothing is stored. Replacing the signing key ends every credential at once.

## Limits

| Who | Limit |
| --- | --- |
| Without a token, per IP address | 120 requests a minute across the API, MCP and A2A |
| With a token, per registration | 600 requests a minute |
| Registration and token exchange, per IP address | 10 requests a minute |

Past a limit the answer is `429` with `Retry-After` (seconds).

## Errors

Registration and token exchange answer OAuth errors, `{"error": "...", "error_description": "..."}`: `invalid_request`, `unsupported_grant_type`, `invalid_grant` (the assertion expired or was altered: register again), `invalid_scope`, `identity_assertion_not_enabled`, `service_auth_not_enabled`, and `temporarily_unavailable`. The API answers `{"error": {"code": "...", "message": "..."}}` (https://generativeicons.com/developers/).

## Privacy

Registration asks for nothing and stores nothing: the registration id exists only inside the signed tokens, and rate limiting counts requests without storing them. Privacy policy: https://lottiefiles.com/page/privacy-policy

## Changes

Changes follow the versioning policy at https://generativeicons.com/developers/: additions don't break this flow, and credentials will never become required for what is free today without at least six months' notice here.
