# Escuta Produto auth.md

You are an agent. Escuta Produto supports **agentic registration** for its origin-level API (the A2A agent at https://escutaproduto.com/a2a): discover → register → claim (optional) → exchange for an access_token → call the API. It follows the auth.md profile (https://github.com/workos/auth.md) with the **anonymous** method only.

## Step 1: Discover

- Protected resource metadata (RFC 9728): https://escutaproduto.com/.well-known/oauth-protected-resource (`resource`: https://escutaproduto.com). A request to an inbox skill without a token returns `401` with `WWW-Authenticate: Bearer resource_metadata="..."` pointing there.
- Authorization server metadata (RFC 8414): https://escutaproduto.com/.well-known/oauth-authorization-server/api/auth. Its `agent_auth` block lists the identity and claim endpoints used below.

## Step 2: Register (anonymous)

```http
POST https://escutaproduto.com/api/auth/agent/identity
Content-Type: application/json

{ "type": "anonymous" }
```

The response carries `identity_assertion` (a service-signed JWT), `pre_claim_scopes` (`docs:read`), `claim_url`, `claim_token` (returned once; keep it in memory) and `post_claim_scopes` (`inbox:read`). `identity_assertion` and `service_auth` bodies return `issuer_not_enabled` / `service_auth_not_enabled`: they are not supported here.

## Step 3: Exchange the assertion

```http
POST https://escutaproduto.com/api/auth/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<identity_assertion>&resource=https://escutaproduto.com
```

Before a claim the token has `docs:read`: enough for the A2A `docs-search` skill (which is also public). Reading the inbox needs a human to claim the agent.

## Step 4: Claim ceremony (to read the owner's inbox)

1. Start it with the owner's email:
   ```http
   POST https://escutaproduto.com/api/auth/agent/identity/claim
   Content-Type: application/json

   { "claim_token": "clm_...", "email": "owner@example.com" }
   ```
   The response has `claim_attempt.user_code` (6 digits), `verification_uri`, `expires_in` (600 s) and `interval` (5 s).
2. Tell the owner: "Open <verification_uri>, sign in, and enter this code: <user_code>". Only workspace admins can sign in, and the signed-in email must match the one you sent.
3. Poll the token endpoint with `grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=<claim_token>`. You get `authorization_pending` until the owner finishes, `slow_down` if you poll faster than every 5 seconds, `expired_token` when the code window passed (start a new claim) and `access_denied` if the owner refused.
4. On success the response is a token response with scope `inbox:read` (read-only: products, feedback and internal notes) plus a new `identity_assertion`. The pre-claim assertion stops working.

## Step 5: Use and refresh

Send `Authorization: Bearer <access_token>` to https://escutaproduto.com/a2a (skill `inbox-digest`). When it expires, repeat Step 3 with the newest `identity_assertion`; when that fails with `invalid_grant`, register again. Registrations that are never claimed expire after 24 hours.

## Other surfaces

- **Public feedback API: product key, no OAuth.** `POST https://escutaproduto.com/api/v1/feedback` takes the product's public key (`pk_…`) in the JSON body. It can only create feedback. Ask the user for the key rather than guess.
- **Docs MCP server: no credentials.** https://escutaproduto.com/mcp is public and read-only.
- **Owner inbox MCP server: OAuth 2.1.** https://escutaproduto.com/mcp/inbox uses the authorization code flow with PKCE (S256), `resource=https://escutaproduto.com/mcp/inbox`, dynamic client registration (RFC 7591) and a consent page; scopes `inbox:read` and `inbox:write`. Metadata: https://escutaproduto.com/.well-known/oauth-protected-resource/mcp/inbox.
- Tokens are audience-bound: an origin token doesn't work on https://escutaproduto.com/mcp/inbox and vice versa.

## Machine-readable

```json
{
  "resources": [
    {
      "resource": "https://escutaproduto.com/api/v1/feedback",
      "auth": "public_product_key",
      "credential": {
        "prefix": "pk_",
        "location": "JSON body field `key`",
        "obtained_by": "product owner, in the dashboard"
      },
      "access": "write-only (create feedback)"
    },
    {
      "resource": "https://escutaproduto.com/mcp",
      "auth": "none",
      "access": "read-only public docs"
    },
    {
      "resource": "https://escutaproduto.com",
      "auth": "oauth2",
      "protected_resource_metadata": "https://escutaproduto.com/.well-known/oauth-protected-resource",
      "used_by": "https://escutaproduto.com/a2a",
      "scopes": [
        "docs:read",
        "inbox:read"
      ]
    },
    {
      "resource": "https://escutaproduto.com/mcp/inbox",
      "auth": "oauth2",
      "protected_resource_metadata": "https://escutaproduto.com/.well-known/oauth-protected-resource/mcp/inbox",
      "scopes": [
        "inbox:read",
        "inbox:write"
      ],
      "flow": "authorization_code + PKCE (S256)"
    }
  ],
  "agent_registration": {
    "identity_types_supported": [
      "anonymous"
    ],
    "identity_endpoint": "https://escutaproduto.com/api/auth/agent/identity",
    "claim_endpoint": "https://escutaproduto.com/api/auth/agent/identity/claim",
    "token_endpoint": "https://escutaproduto.com/api/auth/oauth2/token",
    "grants": [
      "urn:ietf:params:oauth:grant-type:jwt-bearer",
      "urn:workos:agent-auth:grant-type:claim"
    ],
    "pre_claim_scopes": [
      "docs:read"
    ],
    "post_claim_scopes": [
      "inbox:read"
    ],
    "not_supported": [
      "identity_assertion (ID-JAG)",
      "service_auth"
    ]
  }
}
```

See also: https://escutaproduto.com/docs/api.md, https://escutaproduto.com/.well-known/agent-card.json, https://escutaproduto.com/.well-known/agent-skills/index.json
