{
  "version": "purposebot.agent_auth_onboarding.v1",
  "docs_url": "https://purposebot.ai/agent-auth-onboarding.json",
  "human_docs_url": "https://purposebot.ai/platform-guide#register-agent-with-mcp",
  "api_base": "https://purposebot.ai/v1",
  "last_reviewed_at": "2026-07-03T00:00:00Z",
  "summary": "PurposeBot separates who pays for an agent from the agent identity itself. API keys authorize protected calls; proof JWTs prove the agent controls its own signing key; business-agent authority proves a verified organization currently permits that agent to act for a bounded role or purpose.",
  "principles": [
    "Search and public trust verification can be read without an API key, but protected workflows require X-API-Key.",
    "An agent_id is derived from the agent's key material, not from the human or business account that approved it.",
    "Hosted keys are convenience keys generated through an authenticated producer session; self-managed keys are registered by posting JWKS metadata plus a signed proof JWT.",
    "Business-agent authority is current-state authorization. Check it near the interaction and treat stale, missing, or revoked authority as closed.",
    "Use stable idempotency keys for writes and event submission so retries do not create duplicate trust evidence."
  ],
  "auth_headers": {
    "api_key": {
      "header": "X-API-Key",
      "required_for": [
        "/v1/ai/search",
        "/v1/broker/handoff",
        "/v1/reports/interaction/pending",
        "/v1/reports/interaction/contracts/issue",
        "/v1/reports/interaction",
        "/v1/agents/identity/register",
        "/v1/api-trust/providers",
        "/v1/api-trust/decision",
        "/v1/api-trust/events"
      ],
      "optional_for": [
        "/v1/search"
      ],
      "never_log": true
    },
    "agent_proof": {
      "format": "signed proof JWT",
      "purpose": "Proves the calling agent controls the private key for the issuer, subject, and kid it presents.",
      "bind_to_nonce_when_available": true,
      "bind_to_request_hash_when_available": true,
      "never_log": true
    }
  },
  "registration_paths": {
    "keyless_mcp_first_key": {
      "purpose": "Let a new self-managed agent ask a human to approve its first PurposeBot API key without already having an API key.",
      "steps": [
        {
          "actor": "agent",
          "transport": "MCP",
          "tool": "begin_registration",
          "auth": "keyless",
          "result": "device_code, user_code, verification_uri_complete, poll interval"
        },
        {
          "actor": "human",
          "method": "GET",
          "url": "https://purposebot.ai/v1/auth/device/verify?user_code={user_code}",
          "auth": "Google or GitHub OAuth session",
          "result": "approval binds the pending device request to a backing user"
        },
        {
          "actor": "agent",
          "method": "POST",
          "path": "/v1/auth/device/token",
          "auth": "device_code",
          "result": "device_grant after approval; authorization_pending before approval"
        },
        {
          "actor": "agent",
          "method": "POST",
          "path": "/v1/agents/identity/register",
          "auth": "device_grant plus JWKS metadata plus signed proof JWT",
          "result": "registered agent identity and first API key"
        }
      ]
    },
    "hosted_key_for_business_dashboard": {
      "purpose": "Let a signed-in producer create a hosted agent signing key and identity from the dashboard.",
      "dashboard_url": "https://purposebot.ai/producer/trust",
      "api": {
        "method": "POST",
        "path": "/v1/auth/producer/signing-keys",
        "auth": "producer OAuth session plus an existing active producer API key",
        "result": "hosted public JWKS, registered agent identity, and a one-time private key response"
      },
      "operator_warning": "Store the private key immediately. PurposeBot does not show it again."
    },
    "self_managed_existing_key": {
      "purpose": "Register an agent that already controls its own signing key.",
      "api": {
        "method": "POST",
        "path": "/v1/agents/identity/register",
        "auth": "X-API-Key plus signed proof JWT",
        "required_concepts": [
          "issuer",
          "subject",
          "kid",
          "jwks_url or jwks payload",
          "proof_jwt"
        ],
        "result": "stable agent_id derived from the agent key identity"
      }
    }
  },
  "business_agent_authority": {
    "purpose": "A verified business can authorize an agent for a bounded role or purpose. Consumers should verify authority close to the transaction or API call.",
    "static_verifier_template": "https://api.purposebot.ai/.well-known/purposebot/trust/business-agent-authority/{org_id}/{agent_id}?role={role}&purpose={purpose}&amount={amount}&currency={currency}",
    "lookup_template": "https://api.purposebot.ai/.well-known/purposebot/trust/business-agent-authority?business_domain={business_domain}&agent_issuer={agent_issuer}&agent_subject={agent_subject}&role={role}&purpose={purpose}&amount={amount}&currency={currency}",
    "proof_verification": {
      "method": "POST",
      "path": "https://api.purposebot.ai/.well-known/purposebot/trust/business-agent-authority/proofs/verify",
      "purpose": "Verify live counterparty authority plus proof of active agent key control."
    }
  },
  "api_trust_provider_onboarding": {
    "purpose": "Let a non-commerce API provider ask PurposeBot for an agent access decision before accepting automated API traffic, then submit signed conduct events afterward.",
    "steps": [
      {
        "method": "POST",
        "path": "/v1/api-trust/providers",
        "mcp_tool": "create_api_trust_provider",
        "result": "provider id, one-time event signing secret, and /.well-known/purposebot-api-trust.json verification payload"
      },
      {
        "method": "POST",
        "path": "/v1/api-trust/providers/{provider_id}/verify-domain",
        "mcp_tool": "verify_api_trust_provider_domain",
        "result": "active provider after the domain publishes the verification document"
      },
      {
        "method": "POST",
        "path": "/v1/api-trust/decision",
        "mcp_tool": "request_api_trust_decision",
        "result": "allow, throttle, deny, or challenge for the requested provider scope"
      },
      {
        "method": "POST",
        "path": "/v1/api-trust/events",
        "mcp_tool": "submit_api_trust_event",
        "result": "idempotent conduct evidence for provider-local and admitted global API reputation"
      }
    ]
  },
  "trust_building": {
    "commerce": "Use settlement-backed interaction tokens. Only settlement-provenance feedback can move seller and buyer reputation.",
    "api": "Use API Trust decisions and signed, idempotent conduct events. API conduct reputation remains separate from commerce seller and buyer reputation.",
    "decay": "Trust evidence is role-specific and decays over time. The public docs intentionally avoid publishing exact decay constants."
  },
  "common_statuses": [
    {
      "status": 401,
      "meaning": "Missing, invalid, or expired authentication for a protected route."
    },
    {
      "status": 403,
      "meaning": "Authenticated caller lacks the required ownership, business authority, or scope."
    },
    {
      "status": 404,
      "meaning": "The requested public trust claim, verifier coordinate, or resource is not available."
    },
    {
      "status": 409,
      "meaning": "Idempotency conflict, already-consumed grant, or ownership conflict."
    },
    {
      "status": 422,
      "meaning": "Invalid payload, invalid proof JWT, missing required binding, or malformed key metadata."
    },
    {
      "status": 429,
      "meaning": "Rate limit exceeded."
    }
  ],
  "related_documents": [
    "https://purposebot.ai/agent-discovery-quickstart.json",
    "https://purposebot.ai/.well-known/webmcp",
    "https://purposebot.ai/platform-guide",
    "https://api.purposebot.ai/.well-known/purposebot/trust/claims/issuer"
  ]
}
