{
  "openapi": "3.1.0",
  "info": {
    "title": "Passport.Me API",
    "version": "1.1.0",
    "summary": "Identity-backed data bridge — Gmail, Calendar, Drive, Docs, Sheets, Contacts, wallet activity, and portable AI memories as MCP tools.",
    "description": "Passport.Me exposes three authentication surfaces:\n\n1. **Public discovery endpoints** — no auth. Landing, icons, bonus, health, catalog, metrics beacon.\n2. **Session-cookie endpoints** — browser dashboard at `my.passport.me`. Set-Cookie after Google OAuth / wallet connect.\n3. **OAuth 2.1 endpoints** — remote agents (Claude, ChatGPT, Cursor) register via DCR at `/register`, then authorize against `/oauth/authorize` for the `passport.mcp` scope. Present the access token as `Authorization: Bearer` against `https://mcp.passport.me`.\n\nFull discovery via `/.well-known/api-catalog`. OAuth metadata at `/.well-known/oauth-authorization-server`.",
    "contact": {
      "name": "Passport.Me",
      "url": "https://passport.me",
      "email": "support@passport.me"
    },
    "license": {
      "name": "Terms of Service",
      "url": "https://passport.me/terms"
    }
  },
  "servers": [
    {
      "url": "https://passport.me",
      "description": "Passport.Me public API + dashboard surface"
    },
    {
      "url": "https://mcp.passport.me/mcp",
      "description": "MCP streamable HTTP endpoint (OAuth-gated)"
    }
  ],
  "tags": [
    {
      "name": "Discovery",
      "description": "Unauthenticated catalog + status endpoints."
    },
    {
      "name": "OAuth",
      "description": "OAuth 2.1 DCR + token flow for remote agents."
    },
    {
      "name": "Session",
      "description": "Session-cookie endpoints for the dashboard at my.passport.me."
    },
    {
      "name": "MCP",
      "description": "Model Context Protocol endpoint."
    },
    {
      "name": "Analytics",
      "description": "Product analytics beacon (fire-and-forget)."
    }
  ],
  "paths": {
    "/api/passport/health": {
      "get": {
        "operationId": "getHealth",
        "tags": [
          "Discovery"
        ],
        "summary": "Worker health + configuration snapshot",
        "description": "Reports whether Google / WalletConnect are configured, the MCP URL, and which source keys are available. Safe to call anonymously; does not leak secrets.",
        "security": [],
        "responses": {
          "200": {
            "description": "Health payload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/catalog": {
      "get": {
        "operationId": "getCatalog",
        "tags": [
          "Discovery"
        ],
        "summary": "Public source + app catalog",
        "description": "Merged constants + admin overrides. Lists every data source (Google, wallet) and AI app (Claude, ChatGPT, extensions) rendered by the dashboard. Includes disabled entries flagged as \"coming soon\".",
        "security": [],
        "responses": {
          "200": {
            "description": "Catalog payload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Catalog"
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/landing": {
      "get": {
        "operationId": "getLanding",
        "tags": [
          "Discovery"
        ],
        "summary": "Public landing carousel catalog",
        "description": "Returns the 5-slide carousel shown on the Passport.Me homepage. Cached 5 minutes at the edge.",
        "security": [],
        "responses": {
          "200": {
            "description": "Landing catalog",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LandingCatalog"
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/icons": {
      "get": {
        "operationId": "getIcons",
        "tags": [
          "Discovery"
        ],
        "summary": "Public icon catalog",
        "description": "Returns the SVG icon catalog used by the passport dashboard (nav, UI, source, app categories).",
        "security": [],
        "responses": {
          "200": {
            "description": "Icon catalog",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IconCatalog"
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/bonus/catalog": {
      "get": {
        "operationId": "getBonusCatalog",
        "tags": [
          "Discovery"
        ],
        "summary": "Public bonus point catalog",
        "description": "Returns the admin-maintained bonus catalog (task IDs, point values, labels) used to render the bonus breakdown card.",
        "security": [],
        "responses": {
          "200": {
            "description": "Bonus catalog",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BonusCatalog"
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/metrics/event": {
      "post": {
        "operationId": "emitMetricsEvent",
        "tags": [
          "Analytics"
        ],
        "summary": "Fire a product-analytics event",
        "description": "Fire-and-forget beacon. Event names are allowlisted server-side (see body schema). Rate-limited 300 events / 5 min / IP. Response is 204 on success; unknown event names return 400.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MetricsEvent"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Accepted (no body)."
          },
          "400": {
            "description": "Invalid request payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate-limited.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/register": {
      "post": {
        "operationId": "registerOauthClient",
        "tags": [
          "OAuth"
        ],
        "summary": "Dynamic Client Registration (RFC 7591)",
        "description": "Register an OAuth client. Redirects must be a vetted AI-client host, loopback, or a Chrome extension. Clients with a `chromiumapp.org` redirect outside the `PASSPORT_CHROME_EXTENSION_IDS` allowlist land in `approval_status=pending`; pending and rejected clients cannot complete authorization.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "redirect_uris"
                ],
                "properties": {
                  "redirect_uris": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    },
                    "description": "Array of redirect URIs. At least one required."
                  },
                  "client_name": {
                    "type": "string"
                  },
                  "token_endpoint_auth_method": {
                    "type": "string",
                    "enum": [
                      "none"
                    ],
                    "description": "Public clients only."
                  },
                  "grant_types": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "authorization_code",
                        "refresh_token"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Client registered",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "client_id": {
                      "type": "string"
                    },
                    "client_id_issued_at": {
                      "type": "integer"
                    },
                    "redirect_uris": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "token_endpoint_auth_method": {
                      "type": "string"
                    },
                    "grant_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "response_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate-limited.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/oauth/authorize": {
      "get": {
        "operationId": "oauthAuthorize",
        "tags": [
          "OAuth"
        ],
        "summary": "Authorization endpoint (RFC 6749 §3.1)",
        "description": "Browser-facing authorization endpoint. Presents a consent UI to the logged-in Passport user. Agents should open this URL in the user's browser rather than fetching it server-side. Supports PKCE (S256 required).",
        "security": [],
        "parameters": [
          {
            "name": "response_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "code"
              ]
            }
          },
          {
            "name": "client_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "scope",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "passport.mcp"
              ]
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code_challenge",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code_challenge_method",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "S256"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Consent HTML page (when the user has not yet decided)."
          },
          "302": {
            "description": "Redirect back to `redirect_uri` with `code` + `state` on approval, or `error` on denial."
          }
        }
      }
    },
    "/oauth/token": {
      "post": {
        "operationId": "oauthToken",
        "tags": [
          "OAuth"
        ],
        "summary": "Token endpoint (RFC 6749 §3.2)",
        "description": "Exchange an authorization code or refresh token for an access token. PKCE code_verifier required. Refresh tokens rotate on every use; reuse triggers family invalidation (OAuth 2.1 §4.3.1).",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "grant_type",
                  "client_id"
                ],
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "enum": [
                      "authorization_code",
                      "refresh_token"
                    ]
                  },
                  "client_id": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string",
                    "description": "Required for authorization_code grant."
                  },
                  "redirect_uri": {
                    "type": "string",
                    "format": "uri",
                    "description": "Required for authorization_code grant."
                  },
                  "code_verifier": {
                    "type": "string",
                    "description": "PKCE verifier. Required for authorization_code grant."
                  },
                  "refresh_token": {
                    "type": "string",
                    "description": "Required for refresh_token grant."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token issued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": {
                      "type": "string"
                    },
                    "token_type": {
                      "type": "string",
                      "enum": [
                        "Bearer"
                      ]
                    },
                    "expires_in": {
                      "type": "integer"
                    },
                    "refresh_token": {
                      "type": "string"
                    },
                    "scope": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "invalid_grant / invalid_client / family revoked."
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "mcpCall",
        "tags": [
          "MCP"
        ],
        "summary": "MCP streamable HTTP endpoint",
        "description": "Opaque JSON-RPC body forwarded to the MCP server. Use the MCP client SDK rather than calling this directly. Served from https://mcp.passport.me/mcp.",
        "servers": [
          {
            "url": "https://mcp.passport.me/mcp"
          }
        ],
        "security": [
          {
            "passportOAuth": [
              "passport.mcp"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true,
                "description": "MCP JSON-RPC request (see modelcontextprotocol.io for the full schema)."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "MCP JSON-RPC response (may be a stream of server-sent events).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid bearer token."
          },
          "403": {
            "description": "Token lacks `passport.mcp` scope or targets a revoked grant."
          },
          "429": {
            "description": "Rate-limited.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/status": {
      "get": {
        "operationId": "getStatus",
        "tags": [
          "Session"
        ],
        "summary": "Current session + connection state",
        "description": "Returns the authed user's Google connection, wallet, connected apps, bonus summary, and admin flag. Primary hydration endpoint for the account dashboard.",
        "security": [
          {
            "passportSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Status payload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Status"
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/apps": {
      "get": {
        "operationId": "listConnectedApps",
        "tags": [
          "Session"
        ],
        "summary": "List apps the user has connected (OAuth/MCP/CLI)",
        "security": [
          {
            "passportSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Connected apps",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid session cookie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/apps/revoke": {
      "post": {
        "operationId": "revokeConnectedApp",
        "tags": [
          "Session"
        ],
        "summary": "Revoke a connected app in one click",
        "security": [
          {
            "passportSession": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "appKey"
                ],
                "properties": {
                  "appKey": {
                    "type": "string"
                  },
                  "authMode": {
                    "type": "string",
                    "enum": [
                      "oauth",
                      "mcp",
                      "cli"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Revoked"
          },
          "400": {
            "description": "Invalid request payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid session cookie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden (CSRF / origin mismatch / rate-limited).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed."
          }
        }
      }
    },
    "/api/passport/mcp/regenerate": {
      "post": {
        "operationId": "regenerateMcpToken",
        "tags": [
          "Session"
        ],
        "summary": "Rotate the user's MCP bearer token",
        "security": [
          {
            "passportSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "New token issued"
          },
          "401": {
            "description": "Missing or invalid session cookie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed."
          }
        }
      }
    },
    "/api/passport/memories": {
      "get": {
        "operationId": "listMemories",
        "tags": [
          "Session"
        ],
        "summary": "List the user's curated AI memories",
        "security": [
          {
            "passportSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Memories list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid session cookie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/memories/save": {
      "post": {
        "operationId": "saveMemory",
        "tags": [
          "Session"
        ],
        "summary": "Create a new AI memory",
        "security": [
          {
            "passportSession": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "content"
                ],
                "properties": {
                  "content": {
                    "type": "string",
                    "maxLength": 4000
                  },
                  "sourceProvider": {
                    "type": "string"
                  },
                  "label": {
                    "type": "string",
                    "maxLength": 200
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved"
          },
          "400": {
            "description": "Invalid request payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid session cookie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden (CSRF / origin mismatch / rate-limited).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed."
          },
          "429": {
            "description": "Rate-limited.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/memories/pin": {
      "post": {
        "operationId": "pinMemory",
        "tags": [
          "Session"
        ],
        "summary": "Pin or unpin a memory to the top of the list",
        "security": [
          {
            "passportSession": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "pinned"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "pinned": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated"
          },
          "400": {
            "description": "Invalid request payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid session cookie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed."
          }
        }
      }
    },
    "/api/passport/chat/providers": {
      "get": {
        "operationId": "listChatProviders",
        "tags": [
          "Session"
        ],
        "summary": "List AI providers available for Ask",
        "description": "Returns the single supported provider (OpenAI) with `platformKeyAvailable` and `model`. Still an array for backwards compatibility; the dashboard reads it for the model label and credits.",
        "security": [
          {
            "passportSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Provider list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid session cookie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/mdt/balance": {
      "get": {
        "operationId": "getMdtBalance",
        "tags": [
          "Session"
        ],
        "summary": "MDT balance + tier + bonus credits",
        "security": [
          {
            "passportSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Balance",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/bonus/summary": {
      "get": {
        "operationId": "getBonusSummary",
        "tags": [
          "Session"
        ],
        "summary": "Per-user bonus credit summary",
        "security": [
          {
            "passportSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Bonus summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/account/export": {
      "get": {
        "operationId": "exportAccountData",
        "tags": [
          "Session"
        ],
        "summary": "Export the user's full data bundle (GDPR)",
        "description": "Downloads a JSON bundle of every user-scoped row (connections, wallets, events, memories, OAuth grants). Rate-limited to 3 / 10 min / account.",
        "security": [
          {
            "passportSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "JSON attachment with Content-Disposition",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid session cookie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate-limited.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/account/activity": {
      "get": {
        "operationId": "getAccountActivity",
        "tags": [
          "Session"
        ],
        "summary": "List recent activity events (audit trail)",
        "security": [
          {
            "passportSession": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Event feed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid session cookie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/passport/account/delete": {
      "post": {
        "operationId": "deleteAccount",
        "tags": [
          "Session"
        ],
        "summary": "Delete the user's account (GDPR/CCPA/LGPD)",
        "description": "Requires `confirmEmail` body field to match the connected Google email.",
        "security": [
          {
            "passportSession": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "confirmEmail"
                ],
                "properties": {
                  "confirmEmail": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deleted"
          },
          "400": {
            "description": "Invalid request payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid session cookie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden (CSRF / origin mismatch / rate-limited).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed."
          }
        }
      }
    },
    "/api/passport/signout": {
      "post": {
        "operationId": "signout",
        "tags": [
          "Session"
        ],
        "summary": "Soft sign-out (clears session cookie, keeps Google tokens)",
        "security": [
          {
            "passportSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Signed out"
          },
          "405": {
            "description": "Method not allowed."
          }
        }
      }
    },
    "/api/passport/disconnect": {
      "post": {
        "operationId": "disconnectGoogle",
        "tags": [
          "Session"
        ],
        "summary": "Revoke Google OAuth + clear stored tokens",
        "description": "Hard disconnect. Next sign-in prompts for consent again. Cascades to `oauth_refresh_tokens` + `connected_apps` so downstream MCP clients holding bearer tokens are revoked too.",
        "security": [
          {
            "passportSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Disconnected"
          },
          "401": {
            "description": "Missing or invalid session cookie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed."
          }
        }
      }
    },
    "/api/passport/wallet/nonce": {
      "post": {
        "operationId": "getWalletNonce",
        "tags": [
          "Session"
        ],
        "summary": "Issue a wallet verification nonce (SIWE)",
        "security": [
          {
            "passportSession": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "address"
                ],
                "properties": {
                  "address": {
                    "type": "string",
                    "description": "EIP-55 checksummed wallet address"
                  },
                  "chainId": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Nonce issued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Invalid request payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed."
          }
        }
      }
    },
    "/api/passport/wallet/verify": {
      "post": {
        "operationId": "verifyWallet",
        "tags": [
          "Session"
        ],
        "summary": "Verify a SIWE signature and attach the wallet",
        "security": [
          {
            "passportSession": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "address",
                  "signature",
                  "message"
                ],
                "properties": {
                  "address": {
                    "type": "string"
                  },
                  "signature": {
                    "type": "string"
                  },
                  "message": {
                    "type": "string"
                  },
                  "chainId": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Wallet attached"
          },
          "400": {
            "description": "Invalid request payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid session cookie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "passportOAuth": {
        "type": "oauth2",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://passport.me/oauth/authorize",
            "tokenUrl": "https://passport.me/oauth/token",
            "refreshUrl": "https://passport.me/oauth/token",
            "scopes": {
              "passport.mcp": "Call MCP tools against the user's Passport (read-only)."
            }
          }
        }
      },
      "passportSession": {
        "type": "apiKey",
        "in": "cookie",
        "name": "passport_session",
        "description": "Session cookie issued after Google OAuth or wallet connect. Not intended for agent use — open `https://my.passport.me` in a browser to obtain one."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "Health": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "googleConfigured": {
            "type": "boolean"
          },
          "walletConnectConfigured": {
            "type": "boolean"
          },
          "redirectUri": {
            "type": "string"
          },
          "mcpUrl": {
            "type": "string"
          },
          "oauthMetadataUrl": {
            "type": "string"
          },
          "availableSources": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Catalog": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "provider": {
                  "type": "string"
                },
                "disabled": {
                  "type": "boolean"
                }
              }
            }
          },
          "apps": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "disabled": {
                  "type": "boolean"
                }
              }
            }
          }
        }
      },
      "Status": {
        "type": "object",
        "description": "Truncated — full shape includes connection, wallet, connectedApps, connectedSources, bonusSummary, etc.",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "connected": {
            "type": "boolean"
          },
          "authed": {
            "type": "boolean"
          },
          "connectionId": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "betaAccess": {
            "type": "boolean"
          },
          "adminAuthorized": {
            "type": "boolean"
          }
        }
      },
      "MetricsEvent": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "enum": [
              "landing_cta_click",
              "trust_section_view",
              "landing_slide_view",
              "landing_scroll_depth",
              "first_run_promise_view",
              "first_run_step_click",
              "welcome_dismiss",
              "sidebar_nav_click",
              "developer_section_view"
            ]
          },
          "path": {
            "type": "string",
            "maxLength": 128
          },
          "props": {
            "type": "object",
            "description": "Shallow properties. Only string/number/boolean values accepted. Total JSON capped at 512 bytes.",
            "additionalProperties": {
              "oneOf": [
                {
                  "type": "string",
                  "maxLength": 128
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                }
              ]
            }
          }
        }
      },
      "LandingCatalog": {
        "type": "object",
        "properties": {
          "slides": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "slot": {
                  "type": "integer"
                },
                "prompt": {
                  "type": "string"
                },
                "beforeText": {
                  "type": "string"
                },
                "sourceLabel": {
                  "type": "string"
                },
                "sourceFields": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "sourceTags": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "aiLabel": {
                  "type": "string"
                },
                "toolTags": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "answerHtml": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "IconCatalog": {
        "type": "object",
        "properties": {
          "icons": {
            "type": "object",
            "properties": {
              "nav": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/components/schemas/Icon"
                }
              },
              "ui": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/components/schemas/Icon"
                }
              },
              "source": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/components/schemas/Icon"
                }
              },
              "app": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/components/schemas/Icon"
                }
              }
            }
          }
        }
      },
      "Icon": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string"
          },
          "svg": {
            "type": "string"
          },
          "viewbox": {
            "type": "string"
          }
        }
      },
      "BonusCatalog": {
        "type": "object",
        "properties": {
          "tasks": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "taskId": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                },
                "points": {
                  "type": "integer"
                },
                "navSection": {
                  "type": "string"
                },
                "appKey": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "externalDocs": {
    "description": "Agent skills, MCP server card, and full discovery catalog",
    "url": "https://passport.me/.well-known/api-catalog"
  }
}