oauth

OAuth (MCP)

The Nest-routed, bearer-authed half of the OAuth 2.1 authorization flow (consent context + decision) — see the MCP & OAuth guide for the full flow including the raw RFC endpoints.

2 endpoints

GET /api/v1/oauth/authorize/context

Client name, scope description, and mcp.access-eligible tenants for the consent screen.

Requires authenticationScopeNo additional permission

Path & query parameters

NameInTypeConstraints
clientIdrequired
querystring≥1 chars
redirectUrirequired
querystring≥1 chars
scoperequired
querystring≥1 chars

curl example

curl
curl -X GET "https://api.yourdomain.com/api/v1/oauth/authorize/context?clientId=institflow-cli-a1b2c3&redirectUri=string&scope=string" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"

Responses

200
NameTypeConstraints
clientNamerequired
string
scoperequired
string
membershipsrequired
array<object>
json
{
  "clientName": "string",
  "scope": "string",
  "memberships": [
    {
      "tenantId": "4332af8b-4332-7332-832a-4332af8b4332",
      "tenantSlug": "string",
      "tenantName": "string",
      "membershipId": "e34c26d7-e34c-734c-84c2-e34c26d7e34c"
    }
  ]
}
400The request could not be read at all — unparseable body, unusable content type, oversized payload (`MALFORMED_REQUEST`). Never a schema failure: those are 422.

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

401Missing, expired or invalid credentials (`UNAUTHORIZED`, `TOKEN_INVALID`, `SESSION_REVOKED`).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

402The tenant’s subscription or license is locked (`PAYMENT_REQUIRED`, `SUBSCRIPTION_SUSPENDED`).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

403Authenticated, but not allowed (`FORBIDDEN`, `FEATURE_DISABLED`, `QUOTA_EXCEEDED`, …).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

404No such resource, or it is not visible to this tenant (`NOT_FOUND`).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

409Conflicts with current state (`CONFLICT`, `VERSION_CONFLICT`, `IDEMPOTENCY_KEY_REUSED`).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

422The request was read but its content is not acceptable: body/query/path/header failed schema validation (`VALIDATION_ERROR`, with `details.issues`), or a domain rule rejected a well-formed value (`VIDEO_URL_INVALID`, …).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

429Rate limit exceeded — see the `RateLimit-*` and `Retry-After` headers (`RATE_LIMITED`).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

500Unexpected server error (`INTERNAL_ERROR`). Never carries a stack trace or SQL.

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

POST /api/v1/oauth/authorize/decision

Approve or deny an MCP client authorization request.

Requires authenticationScopeNo additional permission

Request body

NameTypeConstraints
clientIdrequired
string≥1 chars
redirectUrirequired
string≥1 chars
staterequired
string
codeChallengerequired
string≥1 chars
codeChallengeMethodrequired
enum: "S256"
scoperequired
string≥1 chars
membershipId
string (uuid)
approverequired
boolean

Example

json
{
  "clientId": "institflow-cli-a1b2c3",
  "redirectUri": "string",
  "state": "string",
  "codeChallenge": "string",
  "codeChallengeMethod": "S256",
  "scope": "string",
  "membershipId": "e34c26d7-e34c-734c-84c2-e34c26d7e34c",
  "approve": true
}

curl example

curl
curl -X POST "https://api.yourdomain.com/api/v1/oauth/authorize/decision" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "clientId": "institflow-cli-a1b2c3",
    "redirectUri": "string",
    "state": "string",
    "codeChallenge": "string",
    "codeChallengeMethod": "S256",
    "scope": "string",
    "membershipId": "e34c26d7-e34c-734c-84c2-e34c26d7e34c",
    "approve": true
  }'

Responses

200
NameTypeConstraints
redirectTorequired
string
json
{
  "redirectTo": "string"
}
400The request could not be read at all — unparseable body, unusable content type, oversized payload (`MALFORMED_REQUEST`). Never a schema failure: those are 422.

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

401Missing, expired or invalid credentials (`UNAUTHORIZED`, `TOKEN_INVALID`, `SESSION_REVOKED`).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

402The tenant’s subscription or license is locked (`PAYMENT_REQUIRED`, `SUBSCRIPTION_SUSPENDED`).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

403Authenticated, but not allowed (`FORBIDDEN`, `FEATURE_DISABLED`, `QUOTA_EXCEEDED`, …).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

404No such resource, or it is not visible to this tenant (`NOT_FOUND`).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

409Conflicts with current state (`CONFLICT`, `VERSION_CONFLICT`, `IDEMPOTENCY_KEY_REUSED`).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

422The request was read but its content is not acceptable: body/query/path/header failed schema validation (`VALIDATION_ERROR`, with `details.issues`), or a domain rule rejected a well-formed value (`VIDEO_URL_INVALID`, …).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

428An API-key caller must send an `Idempotency-Key` header (`IDEMPOTENCY_KEY_REQUIRED`).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

429Rate limit exceeded — see the `RateLimit-*` and `Retry-After` headers (`RATE_LIMITED`).

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.

500Unexpected server error (`INTERNAL_ERROR`). Never carries a stack trace or SQL.

Returns the shared `ErrorEnvelope` — `{ error: { code, message, requestId, details? } }`. Every code is listed in the Conventions guide.