> For the complete documentation index, see [llms.txt](https://peoplescourt.ai/llms.txt). This page is also available as Markdown.

# Authentication

Every request that acts on a case sends a bearer token:

```http
Authorization: Bearer <token>
```

Keep tokens on a trusted backend, never in URLs or logs. A token identifies the caller. Authority to act for a party is established separately, through that party’s consent or delegation. Each operation in the [endpoint reference](https://peoplescourt.ai/docs/api/reference.md) lists the credentials it accepts.

## Choose a credential

| Caller | Credential | How to get it |
|---|---|---|
| A person, or an app acting for one person | Account OAuth token | Register a personal client at [/account/authorizations](https://peoplescourt.ai/account/authorizations) and use authorization code with S256 PKCE. |
| A registered autonomous agent | Account OAuth token | Complete and verify the agent account, register an agent client, and use client credentials. |
| A platform acting for many users | Partner role credential | [Apply for partner access](https://peoplescourt.ai/docs/api/request-access.md), then issue role credentials in the partner console. Obtain each principal’s authority separately. |

## Four separate controls

Authorization rests on four independent controls. Satisfying one never implies another.

| Control | Answers |
|---|---|
| Credential and role | Which application is calling? |
| Principal authorization or consent record | Which person or entity may it represent? |
| Case membership | Which side may it represent in this case? |
| Operation scope | Which read or write may it perform? |

A coordinating partner may hold separate claimant and respondent role credentials, but a platform credential is never treated as both parties’ consent.

## Create an account

OAuth clients belong to a verified People’s Court account. [Create an account](https://peoplescourt.ai/account), complete the identity and authority fields for yourself, your organization or your registered autonomous agent, and accept the current Terms and Privacy Notice.

Use a permanent mailbox for case and security notices. Follow the verification email before authorizing a client. If verification is required, the consent page provides a resend action.

## Account OAuth

People’s Court is the authorization server for its own accounts. Register a client at [/account/authorizations](https://peoplescourt.ai/account/authorizations) after verifying the account’s email.

| Client type | Registration |
|---|---|
| Personal | Public and bound to the account |
| Agent | Requires the account’s complete agent identity. The secret is shown once. |
| Partner | Requires an active approved tenant administrator and explicit consent from each represented principal |

A partner credential or an external principal identifier never authorizes an account by itself.

| Endpoint | Path |
|---|---|
| Discovery | `GET /.well-known/oauth-authorization-server` |
| Authorization | `/oauth/authorize` |
| Token and refresh | `POST /api/oauth/token` |
| Introspection | `POST /api/oauth/introspect` |
| Revocation | `POST /api/oauth/revoke` |

Token endpoints accept `application/x-www-form-urlencoded`. Confidential clients authenticate with HTTP Basic or with `client_id` and `client_secret` in the body, never both.

### Authorization code with PKCE

The [Get Started guide](https://peoplescourt.ai/docs/api/get-started.md) uses a personal client registered and authorized for `cases:read filings:write consents:write invitations:write submissions:write records:confirm offline_access`. `records:confirm` is required to confirm the Record; `submissions:write` alone does not authorize that act for a personal client. Add `records:write` for Record-summary corrections and `remedies:write` for appeals, Award corrections and additional-Award requests when needed. Case `availableActions` includes only actions permitted by both the case authority and the current token’s scopes.

Send the person to `/oauth/authorize` with `response_type=code`, `client_id`, the exact registered `redirect_uri`, `code_challenge_method=S256`, a fresh SHA-256 `code_challenge`, an unpredictable `state`, a space-separated `scope`, and `resource=https://peoplescourt.ai/api`. The person reviews the client, redirect, scopes, current Rules, and AI disclosure.

The callback returns a single-use `code`, your unchanged `state`, and the issuer `iss`. Verify `state` and `iss`, then exchange the code within two minutes:

```sh
curl --fail-with-body -sS https://peoplescourt.ai/api/oauth/token \
  -d grant_type=authorization_code \
  -d client_id="$CLIENT_ID" \
  --data-urlencode redirect_uri="https://app.example.com/oauth/callback" \
  -d code="$CODE" \
  -d code_verifier="$CODE_VERIFIER" \
  --data-urlencode resource="https://peoplescourt.ai/api"
```

Wildcard redirects and plain PKCE are refused.

### Client credentials for registered agents

```sh
curl --fail-with-body -sS https://peoplescourt.ai/api/oauth/token \
  -u "$CLIENT_ID:$CLIENT_SECRET" \
  -d grant_type=client_credentials \
  -d scope="cases:read submissions:write" \
  --data-urlencode resource="https://peoplescourt.ai/api"
```

Request only scopes registered for the client. The token acts only as the registered agent account. It never selects a case track, waives an appeal or supplies another principal’s consent.

### Lifetime, refresh, and revocation

Access tokens last five minutes. Request `offline_access` on the code flow to receive a rotating refresh token; client credentials never issue one. Refresh with `grant_type=refresh_token`, the `refresh_token`, client authentication, and the same `resource`. Scope can only narrow. Replaying a code or reusing a refresh token revokes the grant.

To revoke, send `token` and client authentication to the revocation endpoint. Revocation applies from the next authorization check.

A change to the Rules version or hash, or to the AI disclosure version or hash, lapses the grant. Refresh then returns `consent_required`; send the person through authorization to review and accept the new terms. Refresh never renews consent silently, and the account console lists grants that need reacceptance.

A connector grant approved through a consent screen that states the hold behaves differently: the change holds it instead of lapsing it. Refresh, introspection and operations that need only `cases:read` continue; every other operation returns HTTP 403 with code `reacceptance_required` until the person accepts the current Rules and disclosure in their account at `/account/authorizations`. The grant keeps the terms it replaced. Connector grants approved before the hold notice existed, and every other grant, lapse as described above.

### Scopes

| Scope | Allows |
|---|---|
| `cases:read` | The account’s case list and authorized case and record reads |
| `case-material:read` | Eligible exchanged case material when the service offers it and the required sharing approvals are recorded |
| `fees:agentic:write` | A separately authorized filing-payment handle and enrolled-host checkout |
| `executions:report` | Reporting or responding to performance of a served Award; moves no funds |
| `filings:write` | Account-bound party filing (also requires `consents:write`); does not itself accept a case procedure |
| `answers:write` | An Answer, subject to the invitation and exact case consent |
| `submissions:write` | Party submissions the current stage permits |
| `records:confirm` | Confirming the account’s own record |
| `records:write` | Correcting the account’s own record |
| `invitations:write` | An authorized respondent invitation |
| `messages:write` | Authorized procedural messages |
| `remedies:write` | Authorized remedy requests |
| `representatives:manage` | Managing an authorized case representation |
| `procedural:request` | Filing permitted procedural requests |
| `termination:write` | Authorized pre-Award termination requests and confirmations |
| `consents:write` | Explicitly accepting the exact prepared filing packet |
| `offline_access` | A rotating refresh token on the code flow |

Use account tokens with `/api/cases` and the canonical `/api/cases/{id}` operations, not partner-only integration registration routes. Account tokens go through the ordinary account and case authorization checks, never an administrator or reviewer role. A case-bound delegation cannot read a collection or another case. Hosted MCP uses its own resource audience and supports the connector reads and writes listed below. Each tool requires its complete scope set; an API-audience token does not work there.

## Partner credentials

Each partner credential is bound to one role within an approved tenant.

| Role | Use |
|---|---|
| `claimant_agent`, `respondent_agent` | Party acts for their own side. Send `x-pc-party: claimant` or `x-pc-party: respondent` where the endpoint requires it. |
| `platform_orchestrator` | Coordination, such as invitations, procedural notices, webhook management, and settlement binding registration |
| `settlement_adapter` | Settlement execution only, carrying `settlement:execute` |
| `evidence_exporter` | Signed evidence-export notifications |
| `read_only_observer` | Reads only |

**Party capabilities.** Cases with membership authorization do not need `x-arb-party-token`; cases without it require that per-case capability. A party capability proves only the case side. It never selects the legal principal or the evidence signer: submission provenance comes from the case’s participant or active membership and the authenticated credential. If optional `protocolPrincipal` or `protocolActor` assertions conflict with that record, the submission is rejected.

**Claimant-initiated cases** create no respondent API membership before the invitation is accepted. Deliver the invitation’s hosted link privately; the respondent signs in, reviews the terms and files its own Answer. Independent respondent integrations use bilateral draft confirmation to establish membership, as described in [Respond for a party](https://peoplescourt.ai/docs/api/workflows/respond-for-party.md).

**Settlement** is a separate, high-risk boundary. A `platform_orchestrator` may register a digest-bound USD corpus only during the bilaterally authorized window before the record closes, and cannot execute it. The server derives the binding’s actor, principal, and authority-grant metadata from the credential and case; callers cannot choose them. Live or dry-run execution requires a `settlement_adapter` credential that carries only `settlement:execute` and is bound to the exact adapter named by the case binding.

**Webhooks.** Endpoint rotation, delivery inspection and terminal-delivery replay use the platform orchestrator’s `callbacks:manage` capability. A partner cannot inspect or replay another tenant’s deliveries.

**Messages.** Writes require `messages:write` and case access. Party credentials act only for their derived side. Platform orchestrators may send `procedural_notice` only and cannot use messages to file merits content. The limit of 20 messages per credential and case in a rolling hour is enforced atomically when the message commits. See [Procedural messages](https://peoplescourt.ai/docs/api/messages.md).

**Authenticity challenges** use `evidence:challenges:read` and `evidence:challenges:write`, limited to claimant and respondent agents with active membership for their side. The challenged evidence must belong to the same case, come from the opposing side, and already be revealed. Partner credentials cannot resolve challenges.

**Idempotency.** Mutating operations require a caller-generated `Idempotency-Key`. Signed evidence-export notifications are the exception: they deduplicate by authenticated exporter and signed event identity. Reuse a key only for the identical request; a changed request under the same key is rejected.

## Standing authority and filing consent

The consent screen optionally offers a standing grant with named acts, a positive USD amount cap, expiry within one year, and ordinary standard procedure. Account-area records are available under `/api/authorizations/authority-grants`: signed-in GET lists the account’s grants and notices, POST explicitly accepts the displayed current terms and bounds, and DELETE revokes an owned grant by `id`. Standing authority does not replace exact case-specific acceptance of a filing packet or a separate appeal election. Optional `transactionIds` further restrict its scope.

Using `standing_grant` to confirm a filing returns `specific_case_acceptance_required`.
Use case-specific hosted, wallet or authorized exact-packet acceptance instead.
A principal’s token with `consents:write` and no standing bounds can explicitly accept a packet at `POST /api/authorizations/consents` with `draftId`, `termsDigest` and the exact `acceptanceStatement`.
The underlying partner delegation remains separate from case-specific arbitration consent.

## Existing-case partner delegation

A hosted respondent authorizes an approved partner OAuth client with `case_id` naming their existing case. The ordinary code flow creates a grant bound to that account, client, case and approved scopes. It does not create a second case or change the opposing party’s authority.

Alternatively, the partner authenticates to `POST /api/oauth/link-requests` with `case_id`, exact `redirect_uri`, `scope`, `state`, `code_challenge_method=S256` and `code_challenge`. Send the returned `approvalUrl` privately to the principal. The signed-in principal must already belong to that case; the page displays the same consent screen. Approval consumes the one-use link and returns a PKCE-bound code to the registered callback. Both paths create the same delegate grant model. The principal can inspect and revoke either grant in their account.

Direct OAuth party filing requires both `filings:write` and `consents:write` plus the explicit case acceptance fields.
A token with standing bounds cannot accept the prepared procedure terms through a standing grant; the principal must accept that exact packet through a supported case-specific method.
A preparing partner cannot apply a personal-client grant by ID alone.
Revoking an OAuth grant blocks future token use; it does not withdraw an already committed, explicit case-specific consent.
Standing Answer authority checks the typed case amount, transaction, pinned terms and ordinary standard procedure; the exact per-case Answer acceptance remains required.

## Connector clients

A connector is a third-party application, such as an assistant in a model provider's directory, that reaches People’s Court through the hosted MCP resource. A connector client belongs to no People’s Court account, so any account with a verified email may authorize it, and the account console lists and revokes the resulting grant by the connector’s name.

Use the registration methods advertised by `GET /.well-known/oauth-authorization-server`:

- **Client ID metadata document.** When `client_id_metadata_document_supported` is `true`, use an HTTPS metadata URL as `client_id`. Its document must declare that exact `client_id`, a `client_name`, valid `redirect_uris`, and `authorization_code` with optional `refresh_token` grants. If it supplies `token_endpoint_auth_methods_supported`, that nonempty list of method strings must explicitly offer `none`, the endpoint’s sole CIMD authentication method. A valid legacy singular preference outside that intersection cannot override the mutual offer. Without the plural list, `token_endpoint_auth_method` must be absent or `none`; JWT-only metadata remains unsupported. Serve the document publicly without redirects or authentication. The full document digest remains bound to consent. No JWT or JWKS is authenticated or fetched.
- **Dynamic client registration.** When `registration_endpoint` is advertised, submit an RFC 7591 JSON body with `client_name` and `redirect_uris` to that endpoint. `token_endpoint_auth_method` must be absent or `none`. The HTTP 201 response returns a `pcc_` client ID and accepted metadata; no secret is issued. Registration is rate-limited, and an unused registration expires after 90 days. There are no client-registration management endpoints.
- **Pre-registered connector.** Use the supplied client ID and its exact approved redirect URIs.

Public connector authorization-code and refresh requests authenticate with `none`.
For these clients, supplying `client_secret`, `client_assertion` or `client_assertion_type`, including an empty value or HTTP Basic with an empty secret, returns `invalid_client` before consuming a code/refresh token or processing credential replay.
Account-owned confidential clients, existing operator-pre-registered connectors with a client secret, and the separately authenticated MCP-resource token exchange retain their existing authentication contracts.

Redirect URIs use the same rules as account clients: HTTPS, or loopback HTTP on `127.0.0.1`, `[::1]` or `localhost`, with no fragment and no credentials. Register each in its exact canonical form with a path; a wildcard, trailing-dot, uppercase or path-less host is refused with `invalid_redirect_uri`. Loopback redirects match with the port ignored, for those three hosts only, for native clients (RFC 8252 section 7.3); every other redirect must match exactly. As RFC 7591 specifies, an omitted `grant_types` means `authorization_code` only; send `["authorization_code", "refresh_token"]` to use `offline_access`, which is otherwise refused at authorization with `invalid_scope` rather than answered with a refresh token the client could not redeem.

Connector authorization uses the ordinary authorization code flow with S256 PKCE and `resource` set to the hosted MCP resource; a connector client cannot authorize the API audience. The MCP audience needs no `case_id`. The standard connector scopes are:

| Scope | Connector operation |
|---|---|
| `cases:read` | The account’s cases and authorized case, event, Award, manifest, Rules and fee-quote reads |
| `filings:write` | Prepare a filing and confirm it after personal hosted acceptance |
| `answers:write` | Read requirements, prepare an Answer and file the exact personally accepted packet |
| `fees:agentic:write` | Obtain a filing-payment handle after separate explicit payment approval |
| `submissions:write` | Submit an approved brief and an explicit Record response |
| `messages:write` | Post an authorized case message |
| `invitations:write` | Create or rotate an authorized case invitation |
| `records:write` | Request corrections to the account’s Record summary |
| `procedural:request` | File an approved procedural request |
| `executions:report` | Report Award performance without moving money |
| `offline_access` | Rotating refresh token |

When protected-resource metadata additionally advertises `case-material:read`, the corresponding material-read tools require `cases:read case-material:read` and the case’s separate sharing approvals. Request only advertised scopes.

Any other scope is refused with `invalid_scope`, and a connector authorization never offers a standing grant. Personal filing acceptance and Answer acceptance and declarations stay on People’s Court pages. `answers:write` permits preparation and filing after that acceptance; `consents:write` is not a connector scope. Every authorization response, including `access_denied`, carries `iss`; verify it with `state` before exchanging a code.

Every connector tool requires `cases:read`; a write additionally requires its operation scope, such as `cases:read submissions:write` for a brief. The initial HTTP 401 challenge requests `cases:read`. A missing permission returns a 403 `WWW-Authenticate` challenge naming the complete required scope set. Request fresh authorization for that set while retaining previously approved permissions that are still needed. Refresh cannot widen a grant.

Tool descriptors publish OAuth requirements in `_meta["mcp/securitySchemes"]` and `_meta["securitySchemes"]`. Tool-level `insufficient_scope` and `invalid_token` results may also carry `_meta["mcp/www_authenticate"]` for host reauthorization. A case-membership conflict is an application error, not a request for broader OAuth permissions.

Send connector tokens only to their MCP resource. The service calls the API under the same approving account and permissions. Revocation, account suspension or refresh-token reuse invalidates access; changed Rules and disclosure hold a connector grant approved under the hold notice, and lapse an older one. Connector clients do not perform the service’s token exchange or receive a resource-server credential.

For a lapsed grant, a Rules or disclosure change at the token endpoint returns HTTP 400 with `error: "invalid_grant"` and the extension member `code: "consent_required"`; send the person back through authorization. A held grant refreshes normally and its actions return `reacceptance_required` until the person accepts the updated terms in their account. Availability failures are distinct: introspection or exchange with an unavailable dependency returns a retryable 5xx rather than an inactive token.

The resource server’s token exchange retries a lost account-state compare-and-swap up to three total commit attempts.
Each attempt validates the original parent and current authority again; code redemption, refresh redemption and case writes retain their existing behavior.
Exhausted contention returns HTTP 409 with `error: "authorization_conflict"` at the token endpoint.
The MCP exchange phase maps that exact typed failure to `service_unavailable`, so the assistant may retry shortly without requesting fresh authorization.
Case-state and idempotency conflicts retain their existing conflict response.
