> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gumnut.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Exchange OAuth code for JWT

> Exchange OAuth authorization code for application JWT after validating state, nonce, and ID token signature. User is retrieved from or created in the database and details added to the JWT.



## OpenAPI

````yaml https://api.gumnut.ai/openapi.json post /api/oauth/exchange
openapi: 3.1.0
info:
  title: Gumnut API
  description: >-
    The Gumnut API manages photo and video libraries: upload and organize
    assets, search by content, group detected faces into people, and curate
    albums and stacks.


    Headless clients authenticate by sending either a Gumnut API key
    (`apikey_...`) or an OAuth access token as a Bearer token in the
    `Authorization` header. The Gumnut web and mobile apps sign in with a
    first-party session (Clerk session JWT) instead, which is also the only
    credential that can manage API keys.
  contact:
    name: Gumnut
    url: https://www.gumnut.ai/contact
  version: 1.0.0
servers:
  - url: https://api.gumnut.ai
    description: Production
security:
  - apiKeyAuth: []
  - oauthJwtAuth: []
tags:
  - name: assets
    description: >-
      Photos and videos in a library: upload, list and filter, update metadata,
      trash and restore.
  - name: search
    description: >-
      Content-based search over a library's assets, with the same filters as
      asset listing.
  - name: albums
    description: User-curated collections of assets.
  - name: album-assets
    description: Link records connecting albums to their member assets.
  - name: stacks
    description: >-
      Groups of related shots of the same moment, presented as a single unit
      with a cover asset.
  - name: people
    description: Named people, each built from clustered faces.
  - name: faces
    description: Detected faces and their assignment to people.
  - name: libraries
    description: Top-level containers that own assets, albums, people, and everything else.
  - name: events
    description: Change-event feed for keeping client state in sync.
  - name: tasks
    description: Status of background processing tasks.
  - name: users
    description: The authenticated user's profile.
  - name: api-keys
    description: >-
      Create and manage Gumnut API keys. Requires a first-party Gumnut app
      session — API keys and OAuth tokens cannot manage credentials.
  - name: oauth
    description: OAuth flow endpoints for obtaining and refreshing access tokens.
  - name: server
    description: Service health.
paths:
  /api/oauth/exchange:
    post:
      tags:
        - oauth
      summary: Exchange OAuth code for JWT
      description: >-
        Exchange OAuth authorization code for application JWT after validating
        state, nonce, and ID token signature. User is retrieved from or created
        in the database and details added to the JWT.
      operationId: exchange_token
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TokenExchangeRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenExchangeResponse'
        '400':
          description: Invalid authorization code, state, or provider response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
        '429':
          description: >-
            Rate limit exceeded. Retry after the interval in the `Retry-After`
            header.
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security: []
components:
  schemas:
    TokenExchangeRequest:
      properties:
        code:
          anyOf:
            - type: string
            - type: 'null'
          title: Code
          description: Authorization code returned by the OAuth provider after user consent
        state:
          anyOf:
            - type: string
            - type: 'null'
          title: State
          description: State token from the initial auth request, used for CSRF protection
        error:
          anyOf:
            - type: string
            - type: 'null'
          title: Error
          description: >-
            Error code if OAuth provider returned an error instead of
            authorization code
        code_verifier:
          anyOf:
            - type: string
            - type: 'null'
          title: Code Verifier
          description: >-
            PKCE code verifier that corresponds to the code_challenge sent in
            the authorization request
      type: object
      title: TokenExchangeRequest
      description: Request to exchange OAuth code for JWT
    TokenExchangeResponse:
      properties:
        access_token:
          type: string
          title: Access Token
          description: >-
            JWT to send as a Bearer token in the `Authorization` header on
            subsequent requests
        user:
          $ref: '#/components/schemas/UserInfo'
          description: The authenticated user
      type: object
      required:
        - access_token
        - user
      title: TokenExchangeResponse
      description: Response containing JWT and user info
    ErrorResponse:
      title: ErrorResponse
      type: object
      properties:
        detail:
          title: Detail
          type: string
          description: Human-readable explanation of the error.
      required:
        - detail
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    UserInfo:
      properties:
        id:
          type: string
          title: Id
          description: Unique Gumnut user identifier with `intuser_` prefix
        email:
          anyOf:
            - type: string
            - type: 'null'
          title: Email
          description: Email address reported by the OAuth provider; null if not shared
        first_name:
          anyOf:
            - type: string
            - type: 'null'
          title: First Name
          description: Given name reported by the OAuth provider; null if not shared
        last_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Last Name
          description: Family name reported by the OAuth provider; null if not shared
        clerk_user_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Clerk User Id
          description: Identifier of the linked identity-provider account
        is_active:
          type: boolean
          title: Is Active
          description: >-
            Whether the account is active. A token exchange can still succeed
            for an inactive account, but subsequent authenticated API requests
            are rejected with 401
        is_verified:
          type: boolean
          title: Is Verified
          description: >-
            Whether the account is marked verified. An internal account flag,
            not proof of email verification — it can be true even when `email`
            is null
      type: object
      required:
        - id
        - email
        - first_name
        - last_name
        - clerk_user_id
        - is_active
        - is_verified
      title: UserInfo
      description: User information in token exchange response
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
  securitySchemes:
    apiKeyAuth:
      type: http
      scheme: bearer
      description: >-
        Gumnut API key (`apikey_...`) sent as a Bearer token in the
        `Authorization` header. Create and manage keys in the Gumnut app, or
        with the API key endpoints while signed in to it.
    oauthJwtAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Short-lived JWT obtained from the OAuth token exchange, sent as a Bearer
        token in the `Authorization` header.

````