# NetSendo auth.md

> Public NetSendo data (product facts, plans, releases, docs, blog) needs no login. Only the release-alert tools act for one person and need an OAuth 2.1 access token.

## Who this is for

AI agents and apps that want to manage NetSendo release alerts for their user: one email per NetSendo release, sent to the user's own verified email address.

## What needs a token

| Tool (MCP server <https://netsendo.com/mcp>) | Scope |
| --- | --- |
| get_my_release_alerts | alerts:read |
| subscribe_release_alerts | alerts:write |
| unsubscribe_release_alerts | alerts:write |

| Scope | Meaning |
| --- | --- |
| alerts:read | See whether your email address is subscribed to NetSendo release alerts |
| alerts:write | Subscribe your email address to NetSendo release alerts or unsubscribe it |

Without a token these tools answer HTTP 401 with `WWW-Authenticate: Bearer resource_metadata="…"`; with a too narrow token HTTP 403 `insufficient_scope`. All other tools and the REST API <https://netsendo.com/api/v1> stay public.

## Discovery

- Protected resource metadata: <https://netsendo.com/.well-known/oauth-protected-resource/mcp>
- Authorization server metadata: <https://netsendo.com/.well-known/oauth-authorization-server>
- Resource indicator (RFC 8707): <https://netsendo.com/mcp>

## Registration

### 1. Apps: OAuth 2.1 authorization code with PKCE

1. Register a client (RFC 7591): POST JSON with `redirect_uris` (https, or http only for localhost / 127.0.0.1 / [::1]) to <https://netsendo.com/oauth/register>. Public clients use `"token_endpoint_auth_method": "none"`.
2. Send the user to <https://netsendo.com/oauth/authorize> with `response_type=code`, `code_challenge` (S256 only), `state`, `scope` and `resource=https://netsendo.com/mcp`.
3. The user signs in with a code emailed to them and approves. Exchange the code at <https://netsendo.com/oauth/token> with `code_verifier`.

### 2. Agents: auth.md registration (service_auth)

POST JSON to <https://netsendo.com/oauth/agent/identity>:

```json
{"type": "service_auth", "login_hint": "user@example.com", "client_name": "My agent"}
```

`{"type": "identity_assertion", "assertion_type": "verified_email", "assertion": "user@example.com"}` is accepted too; the address is verified the same way. The response contains `claim_token`, and `claim.user_code`, `claim.verification_uri`, `claim.interval`. Show the user the verification link and the code. The user signs in there with a code sent to that email address and types your user_code. Meanwhile poll <https://netsendo.com/oauth/token> with `grant_type=urn:workos:agent-auth:grant-type:claim` and `claim_token` every 5 seconds (`authorization_pending`, `slow_down`, `access_denied`, `expired_token`). A new code: POST `{"claim_token", "email"}` to <https://netsendo.com/oauth/agent/identity/claim>.

## Credentials

- Send the access token only in the `Authorization: Bearer` header, never in a URL.
- Access tokens are JWTs (RS256, `typ: at+jwt`) valid 60 minutes; keys at <https://netsendo.com/oauth/jwks.json>.
- Refresh tokens rotate on every use; reusing an old one revokes the whole chain.

## Revocation

POST `token` to <https://netsendo.com/oauth/revoke> (RFC 7009). Users can also write to security@netsendo.com.

## Limits

Registration 10 per hour per IP; sign-in emails 3 per 15 minutes per address; token endpoint 60 per minute; MCP 60 requests per minute per client.

## Data and privacy

We store the verified email address, the consent (client and scope) and hashed tokens. No password, no other data. Privacy policy: <https://netsendo.com/en/legal/privacy-policy>
