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

# Issue a tenant session

> Mints a short-lived token that **proves** which end user is calling, instead of trusting what the page claims. Your backend asks for it with a server-side API key and hands it to the browser; from then on the widget calls Devic with the session token and the tenant can no longer be forged.

Two rules keep the guarantee honest, and both are enforced:

- A session cannot issue another session. An expiry that the holder can extend is not an expiry.
- The call must come from a server. A request carrying an `Origin` header, or made with a key configured for browser domains, is refused — a session minted with a key that ships in a bundle would prove nothing.

`ttlSeconds` is clamped into the allowed range rather than rejected: ask for a year and you get twelve hours.

**Note the path.** This is the one public endpoint served by the gateway itself rather than proxied, so it is reached at `/api/v1/tenant-sessions` — the `/api` prefix that the rest of the API accepts optionally is required here.



## OpenAPI

````yaml POST /api/v1/tenant-sessions
openapi: 3.0.0
info:
  title: Devic.ai Public API
  description: >-
    Devic.ai is an AI platform that allows you to create, manage, and use AI
    agents for various tasks.
  version: 1.0.0
  contact:
    name: Devic.ai Support
    url: https://devic.ai
  x-logo:
    url: https://devic.ai/logo.png
    altText: Devic.ai Logo
  x-summary: Public API for interacting with Devic.ai platform
servers:
  - url: https://api.devic.ai
    description: Production server
  - url: https://staging-api.devic.ai
    description: Staging server
security:
  - bearerAuth: []
tags:
  - name: Projects
    description: Group agents, assistants, documents and costs into projects
  - name: Documents
    description: >-
      Knowledge base documents: create, version, attach and index markdown
      content for RAG
  - name: Document Folders
    description: Organise knowledge base documents into folders and attach them in bulk
  - name: Files
    description: Upload files and obtain shareable download URLs to attach to messages
  - name: Agents
    description: Endpoints related to AI agents and their operations
  - name: Assistants
    description: Endpoints for interacting with assistants and their specializations
  - name: Tool Servers
    description: Endpoints for managing tool servers and their tool definitions
  - name: Health
    description: API health check endpoints
  - name: Documentation
    description: Endpoints for retrieving markdown documentation
  - name: Integrations
    description: Connect third-party apps and turn them into tools
  - name: Triggers
    description: Start an agent or an assistant from an app event
  - name: Tenant Integrations
    description: Apps that each end user connects for themselves
  - name: Memory
    description: What an assistant remembers between conversations
  - name: Skills
    description: Reusable instruction packs for agents and assistants
  - name: Speech to Text
    description: Audio transcription
  - name: Tenants
    description: Tenants, subtenants and their usage
  - name: MCP Gateway
    description: One MCP endpoint over many servers, with visibility per user
  - name: Tenant Sessions
    description: Tokens that prove which end user is calling
paths:
  /api/v1/tenant-sessions:
    post:
      tags:
        - Tenant Sessions
      summary: Issue a tenant session
      description: >-
        Mints a short-lived token that **proves** which end user is calling,
        instead of trusting what the page claims. Your backend asks for it with
        a server-side API key and hands it to the browser; from then on the
        widget calls Devic with the session token and the tenant can no longer
        be forged.


        Two rules keep the guarantee honest, and both are enforced:


        - A session cannot issue another session. An expiry that the holder can
        extend is not an expiry.

        - The call must come from a server. A request carrying an `Origin`
        header, or made with a key configured for browser domains, is refused —
        a session minted with a key that ships in a bundle would prove nothing.


        `ttlSeconds` is clamped into the allowed range rather than rejected: ask
        for a year and you get twelve hours.


        **Note the path.** This is the one public endpoint served by the gateway
        itself rather than proxied, so it is reached at
        `/api/v1/tenant-sessions` — the `/api` prefix that the rest of the API
        accepts optionally is required here.
      operationId: issueTenantSession
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IssueTenantSessionRequest'
      responses:
        '201':
          description: Session issued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TenantSession'
        '400':
          description: tenantId missing, or ttlSeconds is not a number
        '401':
          description: Unauthorized - Invalid or missing token
        '403':
          description: Issued from a browser, or by another tenant session
        '500':
          description: Internal Server Error
      security:
        - bearerAuth: []
components:
  schemas:
    IssueTenantSessionRequest:
      type: object
      required:
        - tenantId
      properties:
        tenantId:
          type: string
          description: The identity this session proves
          example: acme-corp
        subtenantId:
          type: string
          description: Optional subtenant within the tenant
          example: acme-corp-eu
        ttlSeconds:
          type: integer
          default: 3600
          minimum: 60
          maximum: 43200
          description: Lifetime in seconds. Clamped into range, never rejected.
    TenantSession:
      type: object
      properties:
        token:
          type: string
          description: Send it as the bearer token from the browser
        tokenType:
          type: string
          example: Bearer
        tenantId:
          type: string
        subtenantId:
          type: string
        expiresIn:
          type: integer
          description: Seconds until it expires
        expiresAt:
          type: integer
          format: int64
          description: Epoch milliseconds
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Use JWT token for authentication

````