# auth.md

Poly Syncer accepts autonomous agents. This document tells an agent how to
register, obtain a credential, call the protected resource, and give the
credential back.

## Audience

Agents that want to read a Poly Syncer account programmatically: the plan a
wallet is on and when it expires, alongside the public site data that needs no
credential at all.

Everything published on the site -- pricing, plan limits, payment rules,
documentation, articles -- is readable **without any token** through the MCP
server at `https://www.polysyncer.com/mcp`. Only account-scoped tools require
authorization. Start unauthenticated; only register if you need account data.

## Discovery

| Document | URL |
| --- | --- |
| Protected resource metadata (RFC 9728) | https://www.polysyncer.com/.well-known/oauth-protected-resource |
| Authorization server metadata (RFC 8414) | https://www.polysyncer.com/.well-known/oauth-authorization-server |
| JSON Web Key Set | https://www.polysyncer.com/oauth/jwks.json |
| MCP server card | https://www.polysyncer.com/.well-known/mcp/server-card.json |

Access tokens are RS256-signed JWTs. Validate them against the JWKS above with
`iss = https://www.polysyncer.com` and `aud = https://www.polysyncer.com/mcp`.

## Registration

Registration is open and anonymous. No email address, no human review, no
waiting list. Dynamic client registration follows RFC 7591:

```
POST https://www.polysyncer.com/oauth/register
Content-Type: application/json

{
  "client_name": "Your agent",
  "redirect_uris": ["https://your-agent.example/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_method": "none"
}
```

The response carries a `client_id`, and a `client_secret` when you asked for a
confidential client. `http://127.0.0.1` and `http://localhost` redirect URIs are
accepted so a locally running agent can complete the flow.

## Getting a credential

### Authorization code with PKCE

Use this when a person is present and you are acting for their account.

1. Send the person to `https://www.polysyncer.com/oauth/authorize` with
   `response_type=code`, your `client_id`, a registered `redirect_uri`, the
   `scope` you need, a `state`, and `code_challenge` with
   `code_challenge_method=S256`.
2. Poly Syncer identifies people by wallet signature, so the person connects
   their wallet in the panel and approves the listed scopes.
3. Exchange the returned `code` at
   `https://www.polysyncer.com/oauth/token` with `grant_type=authorization_code`
   and your `code_verifier`.

### Client credentials

Use this when no person is present. The client credentials are an API key
created in the panel by a Pro or Elite subscriber:

```
POST https://www.polysyncer.com/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=psk_<api key id>
&client_secret=<the API key>
&scope=read:site read:subscription
```

The issued token is scoped to the wallet that owns the key.

## Scopes

| Scope | Grants |
| --- | --- |
| `read:site` | Published content, pricing, plan limits, documentation, articles |
| `read:subscription` | The plan the authorizing wallet is on and its expiry |
| `offline_access` | A refresh token, so access survives the browser session |

No scope grants the ability to move funds, place or cancel a trade, change
settings, or read a private key. Poly Syncer is non-custodial and holds no
private keys to expose.

## Using the credential

Send the access token as a bearer token to the MCP server:

```
POST https://www.polysyncer.com/mcp
Authorization: Bearer <access token>
Content-Type: application/json
Accept: application/json

{"jsonrpc":"2.0","id":1,"method":"tools/call",
 "params":{"name":"get_my_subscription","arguments":{}}}
```

Unauthenticated calls to an account-scoped tool answer `401` with a
`WWW-Authenticate: Bearer` header carrying `resource_metadata`, so a compliant
client can discover this document set on its own.

## Revocation

```
POST https://www.polysyncer.com/oauth/revoke
Content-Type: application/x-www-form-urlencoded

token=<refresh token>
```

A subscriber can also revoke the underlying API key at any time from the panel,
which immediately invalidates every credential derived from it. Access tokens
are short-lived and expire one hour after issue.

## Rate limits

The MCP server is not rate limited. Automated clients are welcome; please keep
`read_page` results cached rather than re-fetching the same page in a loop.

## Contact

Security and abuse reports: https://www.polysyncer.com/.well-known/security.txt

## agent_auth

The machine-readable registration block lives in the authorization server
metadata at https://www.polysyncer.com/.well-known/oauth-authorization-server
under the `agent_auth` key, and names this document as its skill,
https://www.polysyncer.com/oauth/register as the registration and claim URI,
and https://www.polysyncer.com/oauth/revoke as the revocation URI.
