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

# Exchange a Pria API key for a JWT

> Validates the `x-api-key` header against the hashed key stored on the user record
and returns a regular Pria JWT (`token`) plus a minimal `profile` envelope. The
JWT is identical in shape and lifetime to the one issued by `POST /api/auth/signin`
— every other authenticated endpoint accepts it via `Authorization: Bearer <jwt>`
or `x-access-token: <jwt>`.

**Important: the API key is NOT a JWT.** Sending the raw `pria_…` key as a
`Authorization: Bearer` value will fail with `Invalid access token jwt malformed`
on the bearer-protected endpoints. You must do the exchange here first.

**Authentication transport:** the API key MUST be sent in the `x-api-key` header,
not `Authorization`. The endpoint has no JWT gate — only the key check.

**Access gating:**
- Key format is enforced: `pria_` followed by 40 hex chars (`/^pria_[0-9a-f]{40}$/`).
  A malformed key returns 401, not 400.
- Lookup uses the 9-char prefix for indexing, then verifies the full SHA-256 hash.
- Only users with `accountType` of `admin` or `super` (and `status !== 'deleted'`)
  can mint a JWT. Demoting a user immediately disables their key.

**Rate limiting:** 100 requests per minute per IP (the shared auth limiter).




## OpenAPI

````yaml /mdx/api-reference/admin/admin-api.json post /api/auth/api-key-signin
openapi: 3.0.0
info:
  title: Pria Admin API
  version: 2.0.1
  description: >-
    Pria API Documentation Praxis's developer platform is a core part of our
    mission to empower organizations to grow better. Our APIs are designed to
    enable teams of any shape or size to build robust integrations that help
    them customize and get the most value out of Pria. All Pria APIs are built
    using REST conventions and designed to have a predictable URL structure.
    <br/>  <br/>They use many standard HTTP features, including methods (POST,
    GET, PUT, DELETE) and error response codes.  <br/> <br/>All API calls are
    made under https://hiimpria.ai/api and all responses return standard JSON.
    In these docs, you'll find lists of all available endpoints for a given API,
    along with interactive code blocks for building requests. For walkthroughs
    of basic usage for these APIs, check out the API guides.
servers:
  - url: https://pria.praxislxp.com
    description: Pria API Server
security: []
tags:
  - name: Authentication
    description: User authentication, registration, and password management (/api/auth)
  - name: OAuth
    description: OAuth authentication providers - Google, GitHub, SSO (/api/auth/oauth)
  - name: User
    description: User profile management and account operations (/api/user)
  - name: User Institutions
    description: User institution memberships and switching (/api/user/institution)
  - name: User Tools
    description: Available tools for authenticated users (/api/user/tools)
  - name: Institutions
    description: Institution settings and configuration (/api/user/institution)
  - name: Conversation
    description: AI conversation and Q&A endpoints (/api/ai)
  - name: Realtime
    description: Real-time voice AI and WebRTC sessions (/api/ai/rt)
  - name: Assistant
    description: AI assistant configuration and management (/api/user/assistant)
  - name: History
    description: Conversation history and favorites (/api/user/history)
  - name: RAG
    description: >-
      Document upload, embedding, and retrieval-augmented generation
      (/api/user/files, /api/user/rag)
  - name: Setting
    description: Instance variables and settings management (/api/user/setting)
  - name: Branding
    description: Digital twin branding and customization (/api/agent/branding)
  - name: Agent
    description: Agent engagement and session management (/api/agent)
  - name: SDK Launch
    description: >-
      SDK launch token signing and verification for secure iframe embedding
      (/api/auth/sdk-sign, /api/auth/sdk-verify)
  - name: Testing
    description: Health checks, diagnostics, and test endpoints (/api/test)
  - name: Admin Accounts
    description: Account management for super admins (/api/admin/account)
  - name: Admin Institutions
    description: Institution management for admins (/api/admin/institution)
  - name: Admin Users
    description: User management for admins (/api/admin/user)
  - name: Admin Entitlements
    description: >-
      User-institution relationships and permissions
      (/api/admin/userInstitution)
  - name: Admin Sessions
    description: Session management for admins (/api/admin/session)
  - name: Admin Histories
    description: Conversation history management and analytics (/api/admin/history)
  - name: Admin Assistants
    description: AI assistant management for admins (/api/admin/assistant)
  - name: Admin Questions
    description: Institution question and prompt management (/api/admin/question)
  - name: Admin Tools
    description: Tool configuration management (/api/admin/tool)
  - name: Admin AI Models
    description: AI model configuration (/api/admin/aimodel)
  - name: Admin MCP Servers
    description: Model Context Protocol server management (/api/admin/mcpserver)
  - name: Admin Feedbacks
    description: User feedback management (/api/admin/feedback)
  - name: Admin Uploads
    description: Upload management (/api/admin/upload)
  - name: Admin Charts
    description: Analytics and visualization chart management (/api/admin/chart)
  - name: Admin Memory
    description: Admin inspection and editing of user/instance memory parameters.
  - name: Admin Usage Limits
    description: Per-user usage-vs-cap reporting and account-wide at-limit counts.
paths:
  /api/auth/api-key-signin:
    post:
      tags:
        - Authentication
      summary: Exchange a Pria API key for a JWT
      description: >
        Validates the `x-api-key` header against the hashed key stored on the
        user record

        and returns a regular Pria JWT (`token`) plus a minimal `profile`
        envelope. The

        JWT is identical in shape and lifetime to the one issued by `POST
        /api/auth/signin`

        — every other authenticated endpoint accepts it via `Authorization:
        Bearer <jwt>`

        or `x-access-token: <jwt>`.


        **Important: the API key is NOT a JWT.** Sending the raw `pria_…` key as
        a

        `Authorization: Bearer` value will fail with `Invalid access token jwt
        malformed`

        on the bearer-protected endpoints. You must do the exchange here first.


        **Authentication transport:** the API key MUST be sent in the
        `x-api-key` header,

        not `Authorization`. The endpoint has no JWT gate — only the key check.


        **Access gating:**

        - Key format is enforced: `pria_` followed by 40 hex chars
        (`/^pria_[0-9a-f]{40}$/`).
          A malformed key returns 401, not 400.
        - Lookup uses the 9-char prefix for indexing, then verifies the full
        SHA-256 hash.

        - Only users with `accountType` of `admin` or `super` (and `status !==
        'deleted'`)
          can mint a JWT. Demoting a user immediately disables their key.

        **Rate limiting:** 100 requests per minute per IP (the shared auth
        limiter).
      parameters:
        - in: header
          name: x-api-key
          required: true
          schema:
            type: string
            pattern: ^pria_[0-9a-f]{40}$
          description: >-
            Pria API key (`pria_` + 40 hex chars). Provisioned by an admin via
            the admin UI.
          example: pria_0d59f32058727e990bbd5cbdac7668dc2e2c6c09
      responses:
        '200':
          description: Key accepted — JWT and minimal profile returned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiKeySigninResponse'
        '400':
          description: '`x-api-key` header is missing or not a string.'
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  message:
                    type: string
                    example: x-api-key header is required
        '401':
          description: >
            Key is malformed, unknown, or the bound user is not admin/super (or
            is deleted).

            The handler returns the same generic message for all three cases to
            avoid

            leaking which keys exist.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  message:
                    type: string
                    example: Invalid API key
        '403':
          description: |
            The key is valid but this source is not on its authorized-source
            allowlist AND enforcement is enabled for that key
            (`PUT /api/user/api-key/sources`). Network entries match the
            resolved client IP; web-origin entries match the `Origin` header,
            so a server-side caller (which sends no `Origin`) is denied by an
            origin-only list. Distinct from 401 so integrations can tell
            "wrong source" from "bad key".
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  message:
                    type: string
                    example: API key not authorized from this source
                  code:
                    type: string
                    example: source_not_allowed
        '429':
          description: Too many requests (IP-level abuse limiter — 100/min).
        '500':
          description: Internal server error during signin.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  message:
                    type: string
                    example: 'Sign-in failed: <error details>'
      security:
        - priaApiKey: []
components:
  schemas:
    ApiKeySigninResponse:
      type: object
      properties:
        token:
          type: string
          description: >
            JWT signed for the API-key-bound user. Use it in subsequent calls
            via

            `Authorization: Bearer <token>` or the `x-access-token` header.
            Token TTL

            matches the normal signin flow (6 hours by default, configurable via

            `JWT_VALIDITY_SEC`).
          example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
        profile:
          type: object
          description: |
            Minimal profile envelope tailored for SDK / integration consumers.
            Smaller than the regular signin profile — see properties below.
          properties:
            _id:
              type: string
              example: 6430736fd62d650040420674
            email:
              type: string
              format: email
              example: integration-bot@praxis-ai.com
            fname:
              type: string
              example: Integration
            lname:
              type: string
              example: Bot
            accountType:
              type: string
              enum:
                - admin
                - super
              description: API-key signin is gated to admin/super accounts only.
              example: admin
            plan:
              type: string
              example: pro
            status:
              type: string
              example: active
            credits:
              type: integer
              example: 1000
            creditsUsed:
              type: integer
              example: 12
            institution:
              type: object
              nullable: true
              description: >-
                Trimmed institution summary (only set when the user belongs to
                one).
              properties:
                _id:
                  type: string
                  example: 68793ef2a8a4a5eaff36e7ca
                name:
                  type: string
                  example: domain.edu
                status:
                  type: string
                  example: active
                credits:
                  type: integer
                  example: 500
                ainame:
                  type: string
                  example: Hugo
  securitySchemes:
    priaApiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: >
        Long-lived Pria API key (format `pria_<40 hex chars>`) used to obtain a
        JWT via

        `POST /api/auth/api-key-signin`. Only valid on the api-key-signin
        endpoint —

        every other admin/user endpoint expects the JWT issued by that exchange
        (sent as

        `Authorization: Bearer <jwt>` or `x-access-token: <jwt>`).

````