Agents · approveOAuthRequest
Connect a connector
POST /v1/oauth/requests/{id}/approve
Connects the MCP client in the request's workspace (Logu-Workspace): as a new agent named agentName (default: the client's name), or with agentId as an existing agent of that workspace. Returns redirectTo, the client's redirect URI with a one-time code (2 minutes): the app sends the browser there, and the client exchanges the code at POST /oauth/token. The connector then shows among the agent's API keys (connector set); revoking it or deleting the agent disconnects the client. Deciders and Owners only. Recorded in the activity log (agent.created for a new agent, agent.connected, then api_key.created, each with via: oauth).
- Who may call it
- humans: Deciders and up
- Server
- https://api.logu.dev
Parameters#
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | required | The OAuth request's id (oar_…), from the /connect?request= link. · e.g. oar_Tq9mZ2xK7pW4vR8nB3cY6dF1gH5jL0sA |
Logu-Workspace | header | string | optional | Humans only: the workspace to act in (default: your personal workspace). Agents always act in their API key's workspace. · e.g. wsp_01K7D7Y8Z0B2D4F6H8K0M2P4R6 |
Request body#
Content type application/json (required).
| Field | Type | Required | Notes |
|---|---|---|---|
agentName | string | optional | 1–64 chars |
agentId | string | optional | 1–64 chars |
{
"agentName": "Claude"
}
Example#
curl -s -X POST "https://api.logu.dev/v1/oauth/requests/oar_Tq9mZ2xK7pW4vR8nB3cY6dF1gH5jL0sA/approve" \
-H "Authorization: Bearer $LOGU_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"agentName":"Claude"}'
Responses#
200
The agent (new or existing), its workspace and where to send the browser.
{
"agent": {
"id": "agt_01K7D8F2H4K6M8P0R2T4V6X8Z0",
"name": "Claude"
},
"existing": false,
"workspace": {
"id": "wsp_Xq3bY7tLmN2pR8sV",
"name": "Ana"
},
"redirectTo": "https://claude.ai/api/mcp/auth_callback?code=Yk3Jq8pW2vR6tN0mX4cB7dF9gH1jK5lZ&state=af0ifjsldkj&iss=https%3A%2F%2Fapi.logu.dev"
}
Response fields
| Field | Type | Required | Notes |
|---|---|---|---|
agent | AgentRef | required | |
agent.id | string | required | |
agent.name | string | required | |
existing | boolean | required | |
workspace | object | required | |
workspace.id | string | required | |
workspace.name | string | required | |
redirectTo | string | required |
Errors#
Every error is {"error":{"code","message","hint","docUrl","requestId"}}: branch on code. See Errors.
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request | The request is malformed or a field is invalid (see issues). |
| 400 | unknown_field | The body has a field the endpoint doesn't know (often a typo or snake_case). |
| 401 | unauthorized | No credentials, or the API key or session is invalid or revoked. |
| 402 | plan_limit | This is over one of the workspace's plan quotas: asks, events or metric reports this month, stored images, projects or metric names (Free and Pro), or on Free its agents, members and webhook endpoints (only on servers that enforce plan limits), or a Free account that already owns its shared workspaces (always). |
| 402 | ceiling_reached | The workspace reached one of Logu's cost ceilings (asks, events, metric reports, test traffic or images this month, stored image bytes, projects, metric names or API keys). Unlike plan_limit, upgrading doesn't lift it. An account that already owns the most shared workspaces an account may own gets it too. |
| 403 | forbidden | The caller is authenticated but may not do this (wrong role, or an API key on a human-only endpoint). |
| 404 | not_found | No such route, or the resource doesn't exist in your workspace. |
| 409 | conflict | The resource isn't in a state that allows this: an ask that is no longer waiting (ask has its current state), an invitation no longer pending, the last Owner. |
| 500 | internal_error | Something went wrong on Logu's side. |