Start an authorization (browser redirect)
/oauth/authorize
Validates the request, parks it server-side, and redirects the browser to Elaichi's consent screen — this endpoint never renders HTML and never returns a code directly. PKCE is mandatory: `code_challenge` with `code_challenge_method=S256`; an absent method is rejected rather than defaulting to `plain`. Nothing about the request travels through the browser afterwards — the redirect carries only an opaque request id, so there is nothing for a user-agent to tamper with. If the user is not signed in they are sent to login first and returned to the same consent URL. The consent screen then calls `GET /oauth/authorize-request/{id}` and one of approve/deny. Errors before the redirect URI is validated are rendered as an RFC 6749 error body (an unregistered URI must never be redirected to, or the error path becomes an open redirect); errors after it are appended to the registered redirect URI as `error`/`error_description` with `state` echoed back. Rate limited per `client_id`.
Query Parameters
From POST /oauth/register (ocli_…).
Must exactly match one of the URIs registered for this client.
Only code is supported.
code
PKCE challenge: base64url, 43–128 characters.
Must be S256. plain and an absent value are both rejected.
S256
MCP scopes, space-delimited on the wire. mcp:read reads org data; mcp:write creates and changes it; mcp:destructive deletes and removes access; mcp:tools invokes the third-party tools the user has connected. openid and email are identity scopes: they authorize GET/POST /oauth/userinfo and grant no MCP access on their own — a grant holding only openid email reaches no mcp:* operation and no connected tool. Requesting mcp:write or mcp:destructive implies mcp:read — a client that can mutate what it cannot read is not a useful capability. Unknown scope values are rejected rather than silently dropped. A request with no scope at all defaults to mcp:read.
Opaque client value, echoed on every redirect back.
RFC 8707 audience. Must identify this server by origin; a resource on another origin is an audience-confusion attempt and is rejected with invalid_target.
curl -X GET 'https://api.elaichi.ai/oauth/authorize' \
-H 'Content-Type: application/json'const response = await fetch('https://api.elaichi.ai/oauth/authorize', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
const data = await response.json();
console.log(data);import os
import requests
url = "https://api.elaichi.ai/oauth/authorize"
headers = {
"Content-Type": "application/json",
}
response = requests.get(url, headers=headers)
print(response.json())