# auth.md: agent authentication for QWeb Spam Shield

This document tells an autonomous agent how to get credentials for the QWeb Spam Shield API. It is the human-readable companion to `/.well-known/oauth-protected-resource` and `/.well-known/oauth-authorization-server`.

## What is open without credentials

These need no token. Read them first; most questions are answered here.

- `https://qwebspamshield.com/llms.txt` — what this site is and does
- `https://qwebspamshield.com/openapi.json` — the machine-readable API description
- `https://qwebspamshield.com/.well-known/api-catalog` — every API this origin publishes
- `https://qwebspamshield.com/api/agent/products` — live catalog and pricing
- `https://qwebspamshield.com/api/agent/status` — service health

## Registration flow

The whole recipe, end to end. Nothing outside this document is needed to follow it.

### 1. Discover

- Authorization server metadata: `https://qweb.qwebmaster.com/.well-known/oauth-authorization-server`
- Protected resource metadata: `https://qwebspamshield.com/.well-known/oauth-protected-resource`

### 2. Register

```http
POST https://qweb.qwebmaster.com/v2/oauth/register
Content-Type: application/json

{
  "client_name": "Your agent",
  "contacts": ["you@example.com"],
  "scope": "read_only"
}
```

`client_name` and at least one valid email in `contacts` are required; an operator has to be able to reach whoever registered before granting anything. The response carries `client_id` and `client_secret`. **Store the secret now, it is shown once.**

### 3. Claim

A new client is `pending` with **no** granted scopes and cannot obtain a token. An operator reviews it and grants scopes. This is deliberate: self-service registration that also self-granted access would be an open door into a platform that issues licenses and moves money.

Poll for the decision instead of retrying the token endpoint:

```http
GET https://qweb.qwebmaster.com/v2/oauth/registration
Authorization: Basic base64(client_id:client_secret)
```

Returns `status` (`pending`, `approved` or `revoked`), the granted `scope`, and a `next_step` in plain words. Poll it at a human pace; approval is a person reading an email.

### 4. Exchange

```http
POST https://qweb.qwebmaster.com/v2/oauth/token
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&scope=read_only
```

Returns `access_token`, `token_type: Bearer` and `expires_in`. Tokens are opaque, not JWTs, which is why no `jwks_uri` is published. `scope` narrows the grant; it can never widen it.

### 5. Use

```http
GET https://qwebspamshield.com/api/agent/products
Authorization: Bearer <access_token>
```

### 6. Handle revocation

A revoked or expired token fails with `401`. Re-run step 4. If that returns `invalid_client` the registration itself was revoked: check step 3 for the reason, and register again only if you still have a legitimate need.

## Scopes

- `read_only`
- `full`
- `module:licensing`
- `module:ai_passthrough`
- `module:subscriptions`
- `module:email`
- `module:antispam`
- `module:tracking`
- `module:outbound_webhooks`
- `commerce`

## Identity and rate limits

- Send a descriptive `User-Agent` naming the operator and a contact URL.
- If you sign requests, publish your keys per Web Bot Auth and send `Signature-Agent`; signed traffic is treated as identified rather than anonymous.
- Anonymous read traffic is rate limited per IP. Authenticated traffic is limited per client.

## Revocation and contact

- Email `support@qwebspamshield.com` to request scope changes, report abuse, or revoke a client.
- `POST https://qwebspamshield.com/api/agent/contact` opens a support ticket without credentials.
- Credentials are revoked immediately on report of compromise; re-register to continue.

## Content use

Content signals for this site are declared in `https://qwebspamshield.com/robots.txt` as `Content-Signal: ai-train=yes, search=yes, ai-input=yes`. Honour them.
