---
title: "Exchange Invitation"
method: POST
path: "/api/v1/console/invitations/exchange"
tags: ["console"]
---

# Exchange Invitation

`POST /api/v1/console/invitations/exchange`

## Request

- Base URL: `https://ndi-api.nace.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://ndi-api.nace.ai/api/v1/console/invitations/exchange`
- Auth: none declared
- TypeScript: <https://skmtc.dev/nace/apis/ndi-service/docs/api/v1/console/invitations/exchange/post.ts> (a function with typed inputs; its response is checked against the schema)

Exchange a live bearer invitation for a bounded first-party session.

## Request body

- PasswordlessInvitationExchangeRequest: Secret copied from an invitation URL fragment.
  - `token` string, password, required

## Response `200`

Successful Response

- PasswordlessInvitationExchangeResponse: A resolved console identity plus its bounded first-party credential.
  - `created` boolean, required: True when this sign-in wrote something: a new identity, a membership from an accepted invitation, or the default organization for an identity that belonged nowhere.
  - `user` ConsoleUserInfo, required: The signed-in OIDC identity. Carries no role: a role is held per organization, so it lives on :class:`~ndi_service.app.schemas.organization.OrganizationInfo`.
    - `id` string, uuid, required
    - `email` string, nullable
    - `created_at` string, date-time, required
  - `organizations` OrganizationInfo[], required: Every organization the user belongs to. Empty means they belong to none yet.
    - `organization_id` string, uuid, required
    - `name` string, required: Storage-safe slug, derived server-side. Stable; not shown to users.
    - `display_name` string, required: The name a human gave the organization.
    - `role` 'owner' | 'admin' | 'member', required: The signed-in user's role here. It may differ per organization.
    - `rate_limit_rpm` integer, required
    - `included_credits` integer, nullable: Lifetime credit allowance; null means unlimited.
    - `joined_at` string, date-time, required
    - `created_at` string, date-time, required
    - `default_workspace_id` string, uuid, nullable: The signed-in user's Perception Playground in this organization — where the console's perception tools upload by default. Null when it has not been provisioned yet, which the console handles by falling back to workspace-free uploads.
  - `can_create_organization` boolean, required: Whether this user may still create an organization themselves.
  - `can_run_evals` boolean: Whether this identity may use the eval console (a Nace staff email domain). The console hides the section when false; the routes enforce it regardless.
  - `access_token` string, required
  - `token_type` 'bearer'
  - `expires_at` string, date-time, required
  - `invited_organization_id` string, uuid, required

## Other responses

- `400`: Bad Request
- `401`: The invitation cannot establish a session.
- `402`: Payment Required
- `403`: Forbidden
- `404`: Not Found
- `409`: Conflict
- `413`: Request Entity Too Large
- `422`: Unprocessable Entity
- `500`: Internal Server Error
- `503`: Service Unavailable

---

[API](https://skmtc.dev/nace/apis/ndi-service.md) - [All operations](https://skmtc.dev/nace/apis/ndi-service/llms.txt) - [OpenAPI document](https://skmtc.dev/nace/apis/ndi-service/revisions/d9d1f8ec2207?raw)
