# Stylome auth.md

You are an agent acting for a Stylome account owner. This service supports
OAuth authorization-code delegation with S256 PKCE and
owner-session API-key provisioning. A human must approve the requested
permissions. API scoring uses the owner's prepaid credits. Do not create
credentials or make paid calls without the owner's approval.

## Discover

- Auth.md: `https://stylome.io/auth.md`.
- Service and OAuth issuer: `https://stylome.io`.
- Protected Resource Metadata: `https://stylome.io/.well-known/oauth-protected-resource`.
- Authorization Server Metadata: `https://stylome.io/.well-known/oauth-authorization-server`.
- Registration endpoint: `POST https://stylome.io/agent/auth`.
- Owner-session registration method: `existing_authenticated_session`.
- Owner-session credential type: `api_key`, sent with `Authorization: Bearer <key>`.
- API contract: `https://stylome.io/api/openapi.json`.
- API instructions: `https://stylome.io/llms.txt`.

Read the authorization server metadata before selecting a flow. Its standard
OAuth fields describe OAuth delegation. Its `agent_auth` extension describes the
separate owner-session provisioning flow below. The extension's `register_uri`
is not OAuth dynamic client registration.

Stylome does not accept ID-JAG, external identity assertions, an email address as
proof of identity, or anonymous paid API registration. It has no WorkOS
`service_auth` claim ceremony, provider revocation-event receiver, or refresh
tokens. Do not send such assertions or poll an invented claim endpoint. The
custom `existing_authenticated_session` method is not the WorkOS
`identity_assertion` or `service_auth` method.

## OAuth delegation

Use the authorization-code flow with a public client and S256 PKCE. The owner
must register the public OAuth client and its exact HTTPS callbacks in an
approved, authenticated, same-origin website browser context:

```http
POST /oauth/clients HTTP/1.1
Host: stylome.io
Origin: https://stylome.io
Content-Type: application/json

{"client_name":"My approved agent","redirect_uris":["https://agent.example/callback"],"scope":"score:create"}
```

The `201` response supplies a `client_id`. This is a public client with
`token_endpoint_auth_method: none`; there is no client secret. A client
registration creates no account, access grant, balance, or credit. Use only a
client and callback that the owner approved. Request the minimum scopes needed.

Read the standard authorization server metadata before each integration. It
advertises the following endpoints:

- Authorization: `https://stylome.io/oauth/authorize`.
- Token exchange: `https://stylome.io/oauth/token`.
- Token revocation: `https://stylome.io/oauth/revoke`.
- Signing keys: `https://stylome.io/oauth/jwks.json`.

Generate a new high-entropy PKCE verifier. Set the challenge to the unpadded
base64url SHA-256 digest of its ASCII bytes. Generate a fresh unpredictable
`state` of 20 to 512 characters. Open the authorization endpoint in the owner's
browser with these query parameters, URL-encoding every value:

```text
response_type=code
client_id=<registered client ID>
redirect_uri=https://agent.example/callback
code_challenge=<S256 challenge>
code_challenge_method=S256
state=<fresh state>
scope=score:create
resource=https://stylome.io
```

The `resource` value is exactly `https://stylome.io`, without a trailing slash.
The owner signs in at Stylome and approves the displayed client, exact callback,
and scopes. Never export the owner's session cookie or Google credentials.
On the callback, verify that `state` matches the original value and `iss` equals
`https://stylome.io`. Stop if either differs. Exchange the one-use code with the
original verifier and exact callback. Do not send a client secret:

```http
POST /oauth/token HTTP/1.1
Host: stylome.io
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&client_id=<client-id>&code=<code>&redirect_uri=https%3A%2F%2Fagent.example%2Fcallback&code_verifier=<original-verifier>&resource=https%3A%2F%2Fstylome.io
```

The JSON response contains `access_token`, `token_type: Bearer`, `expires_in:
3600`, and `scope`. Send it as `Authorization: Bearer <access_token>` only to
`https://stylome.io`. It lasts up to one hour and ends earlier if the approving
browser session signs out or expires, or the owner resets their password.
Obtain fresh owner-approved authorization to continue after any of these events.
Its scopes, zero-content retention, prepaid scoring charges, and owner
revocation are enforced by the normal key lifecycle. A token cannot create
credits or manage the owner's account. The
`score:create` scope permits paid API scoring, so obtain the owner's task and
spending approval before using it.

Revoke an OAuth access token at the discovered revocation endpoint:

```http
POST /oauth/revoke HTTP/1.1
Host: stylome.io
Content-Type: application/x-www-form-urlencoded

client_id=<client-id>&token=<access-token>&token_type_hint=access_token
```

A successful revocation response does not disclose whether the token existed.
There is no refresh token or ID token. Stop paid calls on expiration or
revocation. Obtain fresh owner-approved authorization to replace the credential.

## Owner-session provisioning

1. Ask the owner to approve the agent's purpose, requested scopes, retention
   mode, credential lifetime, and use of prepaid API credits. Never ask for their
   password, Google tokens, session cookie, or payment credentials.
2. The owner signs in at `https://stylome.io/login`, with Google or the available
   verified-email password flow. New owners must complete that same sign-up flow.
3. In the signed-in website's browser context, provision with the request below.
   This requires the HttpOnly `stylome_session` cookie and an exact
   `Origin: https://stylome.io` header. Use a browser request that includes its
   same-origin cookies. A developer Bearer key alone cannot authorize registration.
   Agents without that owner-authorized browser context must ask the owner to
   create a key at `https://stylome.io/developers` and supply only that API key
   through a secure credential channel.

```http
POST /agent/auth HTTP/1.1
Host: stylome.io
Origin: https://stylome.io
Content-Type: application/json

{"name":"My approved agent","scopes":["score:create"],"retention_mode":"zero_content","expires_in":3600}
```

Only `name` is required. Unknown fields are rejected. The defaults are
`scopes: ["score:create"]`, `retention_mode: "zero_content"`, and
`expires_in: 3600` seconds. The lifetime must be an integer from 300 to 86400
seconds. These ordinary opaque API keys have their own expiry and revocation
lifecycle. They do not end when the provisioning browser session signs out or
expires. A password reset revokes these keys through the existing account
security path. Supported scopes are:

- `score:create`: Analyze text. Successful requests, including cache hits, cost
  $5 per million normalized Unicode characters. Registration adds no credits.
- `account:read`: Read API rate limits and prepaid balance.
- `usage:read`: Read API usage metadata.

Request only the scopes needed for the approved task. `zero_content` retains no
submitted text, text hashes, classifier outputs, receipts, or replay state;
normalized character counts and exact costs remain as billing metadata. Choose
`standard` only with the owner's explicit approval of standard API retention.

The `201` JSON response contains `registration_method`, `credential_type`, `key`,
`credential`, `expires_in`, and `warning`. The `credential` contains the public ID,
name, scopes, retention mode, and expiry. The secret `key` appears once. Store it
only in the agent's secure credential store; never put it in a URL, transcript,
repository, or log. Registration is not idempotent; do not automatically retry an
uncertain successful request. Owners can list and revoke keys before retrying.

Errors contain `error` and `error_description`: `session_required` (401),
`invalid_origin` (403), `active_api_key_limit` (409), `request_too_large` (413),
`unsupported_media_type` (415), `invalid_request` (422), `rate_limit_exceeded`
(429, respect `Retry-After`), and `registration_unavailable` (503). The existing
limit of ten active developer keys applies, plus twenty registrations per hour
per owner. Sign-in, balance top-ups, and account ownership are never bypassed.

## Use the credential

Send the API key only to `https://stylome.io` over HTTPS in the Bearer header.
For example, inspect its scope and expiry with:

```http
GET /api/v1/key HTTP/1.1
Host: stylome.io
Authorization: Bearer <key>
```

For scoring, follow the OpenAPI contract and use `POST /api/v1/score` with an
explicit model ID. Do not make paid calls until the owner has approved the task.
No automatic recharge is enabled by agent registration. Personal subscriptions
and prepaid API credits remain separate.

## Revoke or replace

The owner can revoke the public credential ID in the developer dashboard or use
`DELETE https://stylome.io/api/v1/api-keys/{public_id}` in their authenticated
website session. A developer key cannot revoke another key or manage the account.
Expiration and revocation take effect through the normal API-key authentication
path. On an invalid, expired, or revoked key, stop paid calls and ask the owner
for a new approved registration. There is no automatic credential refresh.
