Per User Oauth

Upstream OAuth proxy - authorize with upstream service

Initiates an OAuth flow with an upstream MCP service (Notion, GitHub, etc.) on behalf of the current user. Used during the consent flow (via "Connect" buttons on the MCPs page) and at runtime when a tool call is made to an unauthenticated service.

Consent flow - provide flow_id (from the pending consent flow). The browser-binding cookie (__bifrost_flow_secret) is validated.

Runtime flow - provide session (the Bifrost session ID from the token endpoint). Used when a service was skipped during consent and needs to be connected later.

On success, redirects the user to the upstream provider's authorize URL. After the user grants access, the upstream callback lands at /api/oauth/callback, stores the upstream token against the user's identity, and redirects back to the consent screen (consent flow) or returns an authorization success page (runtime flow).

Authentication is not required - cookie/session validation is performed instead.

GET
/api/oauth/per-user/upstream/authorize
AuthorizationBearer <token>

Bearer token authentication. Use your MPilot virtual-key JWT or admin JWT. Virtual keys (prefixed with sk-bf-) can also be passed here.

In: header

Query Parameters

mcp_client_idstring

ID of the per-user OAuth MCP client to authenticate with

flow_id?string

Pending consent flow ID. Required if session is not provided. The __bifrost_flow_secret cookie must be present and match the flow.

session?string

Bifrost session ID (from the token endpoint). Required if flow_id is not provided. Used for runtime (post-consent) upstream authorization.

Response Body

curl -X GET "https://loading/{AI_GATEWAY_URL}/api/oauth/per-user/upstream/authorize?mcp_client_id=string&flow_id=string&session=string"
Empty
{
  "event_id": "string",
  "type": "string",
  "is_bifrost_error": true,
  "status_code": 0,
  "error": {
    "type": "string",
    "code": "string",
    "message": "string",
    "param": "string",
    "event_id": "string"
  },
  "extra_fields": {
    "provider": "openai",
    "model_requested": "string",
    "request_type": "string"
  }
}
{
  "event_id": "string",
  "type": "string",
  "is_bifrost_error": true,
  "status_code": 0,
  "error": {
    "type": "string",
    "code": "string",
    "message": "string",
    "param": "string",
    "event_id": "string"
  },
  "extra_fields": {
    "provider": "openai",
    "model_requested": "string",
    "request_type": "string"
  }
}
{
  "event_id": "string",
  "type": "string",
  "is_bifrost_error": true,
  "status_code": 0,
  "error": {
    "type": "string",
    "code": "string",
    "message": "string",
    "param": "string",
    "event_id": "string"
  },
  "extra_fields": {
    "provider": "openai",
    "model_requested": "string",
    "request_type": "string"
  }
}
{
  "event_id": "string",
  "type": "string",
  "is_bifrost_error": true,
  "status_code": 0,
  "error": {
    "type": "string",
    "code": "string",
    "message": "string",
    "param": "string",
    "event_id": "string"
  },
  "extra_fields": {
    "provider": "openai",
    "model_requested": "string",
    "request_type": "string"
  }
}
{
  "event_id": "string",
  "type": "string",
  "is_bifrost_error": true,
  "status_code": 0,
  "error": {
    "type": "string",
    "code": "string",
    "message": "string",
    "param": "string",
    "event_id": "string"
  },
  "extra_fields": {
    "provider": "openai",
    "model_requested": "string",
    "request_type": "string"
  }
}
On this page

On this page

No Headings