openapi: 3.0.3
info:
  title: di3 API
  description: 'API for di3 canvases. Authenticate with `Authorization: Bearer <your_api_key>`.'
  license:
    name: ''
  version: 1.0.0
paths:
  /api/canvases:
    get:
      tags:
      - api::canvas
      summary: List all canvases accessible to the authenticated user
      operationId: list_all_canvases
      responses:
        '200':
          description: List of canvases
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/CanvasListItem'
        '401':
          description: Unauthorized
      security:
      - cookie_auth: []
      - api_key: []
    post:
      tags:
      - api::canvas
      summary: Create a new canvas
      operationId: create_canvas_flat
      requestBody:
        content:
          application/json:
            schema: {}
        required: true
      responses:
        '201':
          description: Canvas created
          content:
            application/json:
              schema: {}
        '400':
          description: Invalid request
        '401':
          description: Unauthorized
      security:
      - cookie_auth: []
      - api_key: []
  /api/canvases/{id}:
    get:
      tags:
      - api::canvas
      summary: Get a single canvas by ID
      operationId: get_canvas
      parameters:
      - name: id
        in: path
        description: Canvas ID
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Canvas content
        '401':
          description: Unauthorized
        '404':
          description: Not found
      security:
      - cookie_auth: []
      - api_key: []
    put:
      tags:
      - api::canvas
      summary: Update a canvas
      operationId: update_canvas
      parameters:
      - name: id
        in: path
        description: Canvas ID
        required: true
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema: {}
        required: true
      responses:
        '200':
          description: Canvas updated. `warnings` carries non-fatal guidance on the saved graph - the update already succeeded, but acting on it produces a better diagram.
        '401':
          description: Unauthorized
        '404':
          description: Not found
      security:
      - cookie_auth: []
      - api_key: []
    delete:
      tags:
      - api::canvas
      summary: Delete a canvas
      operationId: delete_canvas
      parameters:
      - name: id
        in: path
        description: Canvas ID
        required: true
        schema:
          type: string
      responses:
        '204':
          description: Canvas deleted
        '401':
          description: Unauthorized
        '404':
          description: Not found
      security:
      - cookie_auth: []
      - api_key: []
  /api/user/api-keys:
    get:
      tags:
      - api::api_keys
      summary: List all API keys for the current user
      operationId: list_api_keys
      responses:
        '200':
          description: List of API keys (raw key values are never returned here)
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ApiKeyResponse'
        '401':
          description: Unauthorized
      security:
      - cookie_auth: []
    post:
      tags:
      - api::api_keys
      summary: Create a new API key (the raw key is returned once - store it securely)
      operationId: create_api_key
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateApiKeyRequest'
        required: true
      responses:
        '201':
          description: API key created - raw key shown only once
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateApiKeyResponse'
        '400':
          description: Invalid request
        '401':
          description: Unauthorized
      security:
      - cookie_auth: []
  /api/user/api-keys/{id}:
    delete:
      tags:
      - api::api_keys
      summary: Revoke an API key
      operationId: revoke_api_key
      parameters:
      - name: id
        in: path
        description: API key ID
        required: true
        schema:
          type: string
      responses:
        '204':
          description: Key revoked
        '401':
          description: Unauthorized
        '404':
          description: Key not found or not owned by you
      security:
      - cookie_auth: []
components:
  schemas:
    ApiKeyResponse:
      type: object
      required:
      - id
      - name
      - key_prefix
      - expires_at
      - created_at
      properties:
        canvasId:
          type: string
          nullable: true
        canvasName:
          type: string
          nullable: true
        created_at:
          type: string
        expires_at:
          type: string
        id:
          type: string
        key_prefix:
          type: string
          description: First 12 characters of the key, for identification only
        last_used_at:
          type: string
          nullable: true
        name:
          type: string
    CanvasListItem:
      type: object
      required:
      - id
      - name
      - nodes_count
      - edges_count
      - canvasType
      properties:
        canvasType:
          type: string
        edges_count:
          type: integer
          format: int64
        id:
          type: string
        is_shared:
          type: boolean
          nullable: true
        name:
          type: string
        nodes_count:
          type: integer
          format: int64
        vaultId:
          type: string
          nullable: true
    CreateApiKeyRequest:
      type: object
      required:
      - name
      properties:
        canvasId:
          type: string
          description: Restrict the key to one canvas ("Agent" key) - the caller must own it.
          nullable: true
        expiresInDays:
          type: integer
          format: int64
          description: Override the default expiry (1 day). Clamped to 1..=365.
          nullable: true
        name:
          type: string
          description: A descriptive name for this key (e.g. "Claude AI access")
    CreateApiKeyResponse:
      allOf:
      - $ref: '#/components/schemas/ApiKeyResponse'
      - type: object
        required:
        - key
        properties:
          key:
            type: string
            description: Full API key value - shown only once, store it securely
  securitySchemes:
    api_key:
      type: http
      scheme: bearer
      bearerFormat: d3k_<token>
    cookie_auth:
      type: apiKey
      in: cookie
      name: token
security:
- api_key: []
- cookie_auth: []
