SageOx API Keys API

The API Keys API from SageOx — 2 operation(s) for api keys.

OpenAPI Specification

sageox-api-keys-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: SageOx Admin API Keys API
  version: 1.0.0
  description: "# API Reference\n\n## Overview\n\nSageOx is a platform that captures team knowledge from discussions, decisions, and work context into a Ledger (per-repo historical record) and Team Context (team-wide shared knowledge). The SageOx API provides programmatic access to manage repositories, recordings, notifications, and team data with high performance and reliability.\n\n## Base URLs\n\n| Environment | URL |\n|---|---|\n| Local Development | `http://localhost:3000` |\n| Test | `https://test.sageox.ai` |\n| Production | `https://sageox.ai` |\n\n## Authentication\n\nAll requests to the SageOx API require authentication via JWT tokens issued by the Better Auth service.\n\nInclude your token in the `Authorization` header:\n```\nAuthorization: Bearer <token>\n```\n\n**Initial Auth Flow (CLI)**\n- CLI initiates device flow to obtain initial credentials\n- Exchange device code for JWT token\n- Store token securely for subsequent API requests\n- Refresh token when expired\n\n**Authenticated Endpoints**\n- Pass JWT in `Authorization: Bearer <token>` header\n- Tokens contain user identity and team membership\n- Invalid or expired tokens return 401 Unauthorized\n\n## Response Format\n\n### Success\nStandard response format with optional pagination metadata:\n```json\n{\n  \"success\": true,\n  \"data\": { ... }\n}\n```\n\n### Error\nAll errors follow a consistent format:\n```json\n{\n  \"success\": false,\n  \"error\": \"Human-readable error description\"\n}\n```\n\n**Status Codes**\n- `400` — Bad Request: Invalid parameters or malformed request\n- `401` — Unauthorized: Missing or invalid authentication token\n- `403` — Forbidden: Insufficient permissions for this resource\n- `404` — Not Found: Resource does not exist\n- `409` — Conflict: Request conflicts with current state (e.g., duplicate)\n- `429` — Rate Limited: Too many requests; retry with backoff\n- `500` — Internal Error: Server error; contact support if persistent\n\n## Pagination\n\nList endpoints support cursor-based pagination via query parameters:\n\n**Query Parameters**\n- `limit` — Number of results per page (default: 20, max: 100)\n- `offset` — Number of results to skip (default: 0)\n\n**Response Metadata**\nList responses include pagination info:\n```json\n{\n  \"success\": true,\n  \"data\": [ ... ],\n  \"meta\": {\n    \"total\": 150,\n    \"limit\": 20,\n    \"offset\": 0,\n    \"hasMore\": true\n  }\n}\n```\n\n## ID Formats\n\nResources use standardized ID formats for easy identification:\n\n| Resource | Format | Length | Example |\n|---|---|---|---|\n| Team | `team_<cuid2>` | 10 chars | `team_abc1234567` |\n| User | `usr_<cuid2>` | 10 chars | `usr_xyz9876543` |\n| Repository | `repo_<uuidv7>` | 36 chars | `repo_01934f5a-8b9c-7def-abcd-0123456789ab` |\n| Recording | `rec_<uuidv7>` | 36 chars | `rec_01934f5a-8b9c-7def-abcd-0123456789ab` |\n| Image | `img_<uuidv7>` | 36 chars | `img_01934f5a-8b9c-7def-abcd-0123456789ab` |\n| Notification | `notif_<cuid2>` | 14 chars | `notif_ab1cd2ef3g` |\n\nUse these IDs for all API operations. IDs are unique across environments.\n\n## Rate Limiting\n\nThe API applies rate limiting to protect against abuse and ensure fair access:\n\n**Authenticated Endpoints**\n- Limited per user: depends on subscription tier\n- Quota resets hourly\n\n**Unauthenticated Endpoints**\n- Limited per IP address\n- More restrictive than authenticated limits\n\nWhen rate limited, the API returns `429 Too Many Requests`. Retry requests with exponential backoff:\n```\nwait = min(2^attempt * 100ms, 10s)\n```\n\n## Timestamps\n\nAll timestamps in API responses use RFC 3339 / ISO 8601 format in UTC:\n```\n2025-12-03T10:30:00Z\n```\n\nUse this format when providing timestamps in requests as well. The API rejects timestamps in other formats.\n\n## SDKs & Tools\n\n- **OpenAPI Spec** — Full schema available at `/api/openapi.json`\n- **Postman Collection** — Import from `/api/postman.json` for interactive exploration\n- **CLI** — Use `ox` CLI for command-line access\n"
  contact:
    name: SageOx Team
  license:
    name: MIT
servers:
- url: http://localhost:3000
  description: Devcontainer
- url: https://test.sageox.ai
  description: Test
- url: https://sageox.ai
  description: Production
security:
- bearerAuth: []
tags:
- name: API Keys
paths:
  /api/v1/api-keys:
    post:
      operationId: createAPIKey
      summary: Create API key
      description: 'Creates a new API key for the authenticated user. The full key is returned

        only once and must be stored securely. The key can be used for API

        authentication via Bearer token. Optionally specify an expiration period.

        '
      tags:
      - API Keys
      security:
      - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - name
              properties:
                name:
                  type: string
                  description: Human-readable name for the API key (1-255 characters)
                  example: Production API Key
                expires_in_days:
                  type: integer
                  nullable: true
                  description: Optional expiration period in days from now
                  minimum: 1
                  example: 365
            examples:
              with_expiration:
                summary: Create key with 365-day expiration
                value:
                  name: Production API Key
                  expires_in_days: 365
              no_expiration:
                summary: Create key with no expiration
                value:
                  name: Permanent API Key
      responses:
        '201':
          description: API key created successfully
          content:
            application/json:
              schema:
                type: object
                required:
                - id
                - name
                - key_prefix
                - created_at
                - key
                properties:
                  id:
                    type: string
                    format: uuid
                    description: Unique API key identifier
                    example: 550e8400-e29b-41d4-a716-446655440000
                  name:
                    type: string
                    description: Key name
                    example: Production API Key
                  key_prefix:
                    type: string
                    description: First 8 characters of the key (safe to log)
                    example: mk_aB1cD2e
                  key:
                    type: string
                    description: Full API key (only returned on creation)
                    example: mk_aB1cD2eF3gH4iJ5kL6mN7oP8qR9sTu
                  created_at:
                    type: string
                    format: date-time
                    description: Key creation timestamp
                    example: '2025-01-20T15:30:00Z'
                  expires_at:
                    type: string
                    format: date-time
                    nullable: true
                    description: Key expiration timestamp (null if no expiration)
                    example: '2026-01-20T15:30:00Z'
                  last_used_at:
                    type: string
                    format: date-time
                    nullable: true
                    description: Last usage timestamp (null if never used)
                    example: null
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                missing_name:
                  value:
                    success: false
                    error: name is required
                invalid_expiration:
                  value:
                    success: false
                    error: expires_in_days must be positive
        '401':
          description: Unauthorized - missing or invalid authentication
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    get:
      operationId: listAPIKeys
      summary: List API keys
      description: 'Returns all active (non-revoked) API keys for the authenticated user.

        Full key values are never returned - only the prefix (first 8 chars) for

        identification, creation date, and usage information.

        '
      tags:
      - API Keys
      security:
      - BearerAuth: []
      responses:
        '200':
          description: API keys retrieved successfully
          content:
            application/json:
              schema:
                type: object
                required:
                - keys
                properties:
                  keys:
                    type: array
                    items:
                      type: object
                      required:
                      - id
                      - name
                      - key_prefix
                      - created_at
                      properties:
                        id:
                          type: string
                          format: uuid
                          description: Unique API key identifier
                          example: 550e8400-e29b-41d4-a716-446655440000
                        name:
                          type: string
                          description: Key name
                          example: Production API Key
                        key_prefix:
                          type: string
                          description: First 8 characters of the key
                          example: mk_aB1cD2e
                        created_at:
                          type: string
                          format: date-time
                          description: Key creation timestamp
                          example: '2025-01-20T15:30:00Z'
                        expires_at:
                          type: string
                          format: date-time
                          nullable: true
                          description: Key expiration timestamp (null if no expiration)
                          example: '2026-01-20T15:30:00Z'
                        last_used_at:
                          type: string
                          format: date-time
                          nullable: true
                          description: Last usage timestamp
                          example: '2025-01-20T16:45:00Z'
        '401':
          description: Unauthorized - missing or invalid authentication
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/api-keys/{id}:
    delete:
      operationId: revokeAPIKey
      summary: Revoke API key
      description: 'Revokes (soft-deletes) an API key. The key cannot be used for authentication

        after revocation. Revocation is permanent and cannot be undone.

        '
      tags:
      - API Keys
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        description: API key UUID to revoke
        schema:
          type: string
          format: uuid
          example: 550e8400-e29b-41d4-a716-446655440000
      responses:
        '204':
          description: API key revoked successfully
        '400':
          description: Invalid key ID format
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                invalid_id:
                  value:
                    success: false
                    error: invalid key id format
        '401':
          description: Unauthorized - missing or invalid authentication
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden - not the owner of this key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                not_owner:
                  value:
                    success: false
                    error: not the owner of this key
        '404':
          description: API key not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    ErrorResponse:
      type: object
      description: Standard error response returned by all endpoints on failure.
      required:
      - success
      - error
      properties:
        success:
          type: boolean
          description: Always `false` for error responses.
          enum:
          - false
        error:
          type: string
          description: Human-readable error message describing what went wrong. Do not parse this programmatically — use HTTP status codes for control flow.
          example: Invalid request parameters
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'JWT token obtained from the auth service (/api/auth/token).

        Token is validated using JWKS from the auth service.

        Required claims: sub (user_id), email, name, tier.

        '