726 lines
20 KiB
YAML
726 lines
20 KiB
YAML
openapi: 3.0.3
|
|
info:
|
|
title: pgvecter API
|
|
version: 0.1.0
|
|
description: Minimal tool API for db query + knowledge base upsert/search.
|
|
security:
|
|
- ApiKeyAuth: []
|
|
servers:
|
|
- url: https://labo.sunamura-llc.com
|
|
description: Production
|
|
paths:
|
|
/health:
|
|
get:
|
|
summary: Health check
|
|
operationId: healthCheck
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/HealthResponse"
|
|
/db/query:
|
|
post:
|
|
summary: Read-only SQL query
|
|
operationId: dbQuery
|
|
description: |
|
|
SELECT-only. Multiple statements are not allowed. Server enforces limits, timeouts,
|
|
and a whitelist of allowed schemas/tables.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/DbQueryRequest"
|
|
responses:
|
|
"200":
|
|
description: Query result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/DbQueryResponse"
|
|
"400":
|
|
description: Invalid SQL
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
/kb/upsert:
|
|
post:
|
|
summary: Upsert document and embedding
|
|
operationId: kbUpsert
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/KbUpsertRequest"
|
|
responses:
|
|
"200":
|
|
description: Upserted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/KbUpsertResponse"
|
|
"400":
|
|
description: Invalid request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"503":
|
|
description: Service not configured (DATABASE_URL not set)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
/kb/search:
|
|
post:
|
|
summary: Vector similarity search
|
|
operationId: kbSearch
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/KbSearchRequest"
|
|
responses:
|
|
"200":
|
|
description: Search result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/KbSearchResponse"
|
|
"400":
|
|
description: Invalid request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"503":
|
|
description: Service not configured (DATABASE_URL not set)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
/kb/delete:
|
|
post:
|
|
summary: Delete documents
|
|
operationId: kbDelete
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/KbDeleteRequest"
|
|
responses:
|
|
"200":
|
|
description: Deleted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/KbDeleteResponse"
|
|
"400":
|
|
description: Invalid request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"503":
|
|
description: Service not configured (DATABASE_URL not set)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
/collections:
|
|
get:
|
|
summary: List collections
|
|
operationId: listCollections
|
|
responses:
|
|
"200":
|
|
description: Collections list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/CollectionsResponse"
|
|
"401":
|
|
description: Unauthorized
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"503":
|
|
description: Service not configured (DATABASE_URL not set)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
/admin/collections:
|
|
get:
|
|
summary: List collections (admin)
|
|
operationId: listCollectionsAdmin
|
|
security:
|
|
- AdminApiKeyAuth: []
|
|
responses:
|
|
"200":
|
|
description: Collections list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/CollectionsResponse"
|
|
"401":
|
|
description: Unauthorized
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"503":
|
|
description: Service not configured (ADMIN_API_KEY or DATABASE_URL not set)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
/admin/api-keys:
|
|
get:
|
|
summary: List API keys (admin)
|
|
operationId: adminApiKeysList
|
|
security:
|
|
- AdminApiKeyAuth: []
|
|
responses:
|
|
"200":
|
|
description: API key list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/AdminApiKeyListResponse"
|
|
"401":
|
|
description: Unauthorized
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"503":
|
|
description: Service not configured (ADMIN_API_KEY not set)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
post:
|
|
summary: Issue API key (admin)
|
|
operationId: adminApiKeysCreate
|
|
security:
|
|
- AdminApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/AdminApiKeyCreateRequest"
|
|
responses:
|
|
"200":
|
|
description: Issued API key (shown once)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/AdminApiKeyCreateResponse"
|
|
"400":
|
|
description: Invalid request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"401":
|
|
description: Unauthorized
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"503":
|
|
description: Service not configured (ADMIN_API_KEY not set)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
/admin/api-keys/{id}:
|
|
patch:
|
|
summary: Update API key metadata (admin)
|
|
operationId: adminApiKeysUpdate
|
|
security:
|
|
- AdminApiKeyAuth: []
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/AdminApiKeyUpdateRequest"
|
|
responses:
|
|
"200":
|
|
description: Updated API key
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/AdminApiKey"
|
|
"400":
|
|
description: Invalid request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"401":
|
|
description: Unauthorized
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"503":
|
|
description: Service not configured (ADMIN_API_KEY not set)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
/admin/api-keys/{id}/revoke:
|
|
post:
|
|
summary: Revoke API key (admin)
|
|
operationId: adminApiKeysRevoke
|
|
security:
|
|
- AdminApiKeyAuth: []
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
"200":
|
|
description: Revoked API key
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/AdminApiKey"
|
|
"401":
|
|
description: Unauthorized
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"503":
|
|
description: Service not configured (ADMIN_API_KEY not set)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
/admin/audit/permissions:
|
|
get:
|
|
summary: List permissions audit logs (admin)
|
|
operationId: listPermissionsAudit
|
|
security:
|
|
- AdminApiKeyAuth: []
|
|
parameters:
|
|
- name: since
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: string
|
|
format: date-time
|
|
description: RFC3339 lower bound for requested_at (inclusive)
|
|
- name: until
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: string
|
|
format: date-time
|
|
description: RFC3339 upper bound for requested_at (inclusive)
|
|
- name: api_key_id
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: string
|
|
description: Filter by API key ID
|
|
- name: limit
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 1000
|
|
description: Max items to return (default 100, max 1000)
|
|
responses:
|
|
"200":
|
|
description: Audit log list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/PermissionsAuditResponse"
|
|
"400":
|
|
description: Invalid request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"401":
|
|
description: Unauthorized
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"503":
|
|
description: Service not configured (ADMIN_API_KEY or DATABASE_URL not set)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
components:
|
|
securitySchemes:
|
|
ApiKeyAuth:
|
|
type: apiKey
|
|
in: header
|
|
name: X-API-KEY
|
|
AdminApiKeyAuth:
|
|
type: apiKey
|
|
in: header
|
|
name: X-ADMIN-API-KEY
|
|
schemas:
|
|
HealthResponse:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: ok
|
|
timestamp:
|
|
type: string
|
|
format: date-time
|
|
required:
|
|
- status
|
|
- timestamp
|
|
DbQueryRequest:
|
|
type: object
|
|
properties:
|
|
sql:
|
|
type: string
|
|
description: SELECT-only SQL
|
|
params:
|
|
type: array
|
|
items: {}
|
|
required:
|
|
- sql
|
|
DbQueryResponse:
|
|
type: object
|
|
properties:
|
|
columns:
|
|
type: array
|
|
items:
|
|
type: string
|
|
rows:
|
|
type: array
|
|
items:
|
|
type: array
|
|
items: {}
|
|
row_count:
|
|
type: integer
|
|
required:
|
|
- columns
|
|
- rows
|
|
- row_count
|
|
KbUpsertRequest:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: Document ID
|
|
doc_id:
|
|
type: string
|
|
description: Parent document ID (defaults to id)
|
|
chunk_index:
|
|
type: integer
|
|
description: Chunk index (defaults to 0)
|
|
collection:
|
|
type: string
|
|
description: Collection name (default "default")
|
|
auto_chunk:
|
|
type: boolean
|
|
description: If true, server splits content into chunks and upserts multiple rows.
|
|
chunk_size:
|
|
type: integer
|
|
description: Chunk size in characters (default 800).
|
|
chunk_overlap:
|
|
type: integer
|
|
description: Overlap size in characters (default 100).
|
|
content:
|
|
type: string
|
|
metadata:
|
|
type: object
|
|
additionalProperties: true
|
|
description: metadata.permissions is not allowed (server enforces permissions.users from API key).
|
|
embedding:
|
|
type: array
|
|
items:
|
|
type: number
|
|
description: Embedding vector (length must match EMBEDDING_DIM). If omitted, server generates via provider.
|
|
required:
|
|
- id
|
|
- content
|
|
KbUpsertResponse:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
doc_id:
|
|
type: string
|
|
updated:
|
|
type: boolean
|
|
chunks:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
chunk_index:
|
|
type: integer
|
|
required:
|
|
- id
|
|
- chunk_index
|
|
required:
|
|
- id
|
|
- doc_id
|
|
- updated
|
|
KbSearchRequest:
|
|
type: object
|
|
properties:
|
|
query:
|
|
type: string
|
|
query_embedding:
|
|
type: array
|
|
items:
|
|
type: number
|
|
description: Optional precomputed embedding vector (length must match EMBEDDING_DIM). If omitted, server generates via provider.
|
|
top_k:
|
|
type: integer
|
|
default: 5
|
|
minimum: 1
|
|
maximum: 50
|
|
collection:
|
|
type: string
|
|
description: Collection name (required if collections not provided)
|
|
collections:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Collection names (required if collection not provided)
|
|
filter:
|
|
type: object
|
|
additionalProperties: true
|
|
description: |
|
|
JSON filter over metadata. Supported operators: eq, in, contains, exists, lt/lte/gt/gte, and/or.
|
|
Example: {"and":[{"eq":{"metadata.source":"crm"}},{"exists":{"metadata.visibility":true}}]}
|
|
Note: metadata.permissions.* in filter is rejected (400).
|
|
required:
|
|
- query
|
|
KbSearchResponse:
|
|
type: object
|
|
properties:
|
|
results:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/KbSearchResult"
|
|
required:
|
|
- results
|
|
KbDeleteRequest:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: Document chunk ID (uuid). Required if doc_id not provided.
|
|
doc_id:
|
|
type: string
|
|
description: Parent document ID (uuid). Required if id not provided.
|
|
collection:
|
|
type: string
|
|
description: Collection name (optional)
|
|
filter:
|
|
type: object
|
|
additionalProperties: true
|
|
description: Required unless id is provided. doc_id-only delete is not allowed (use filter). Optional metadata filter (MCP filter DSL). Permissions filter is always enforced. Supports eq/in/contains/exists/lt/lte/gt/gte and/or. metadata.permissions.* in filter is rejected (400).
|
|
dry_run:
|
|
type: boolean
|
|
description: If true, only returns the number of rows that would be deleted.
|
|
KbDeleteResponse:
|
|
type: object
|
|
properties:
|
|
deleted:
|
|
type: integer
|
|
description: Number of deleted rows
|
|
required:
|
|
- deleted
|
|
KbSearchResult:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
collection:
|
|
type: string
|
|
content:
|
|
type: string
|
|
metadata:
|
|
type: object
|
|
additionalProperties: true
|
|
score:
|
|
type: number
|
|
format: float
|
|
description: Similarity score (0-1). Converted from cosine distance.
|
|
required:
|
|
- id
|
|
- collection
|
|
- content
|
|
- score
|
|
CollectionsResponse:
|
|
type: object
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/CollectionItem"
|
|
required:
|
|
- items
|
|
CollectionItem:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
count:
|
|
type: integer
|
|
required:
|
|
- name
|
|
- count
|
|
AdminApiKey:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
label:
|
|
type: string
|
|
permissions_users:
|
|
type: array
|
|
items:
|
|
type: string
|
|
status:
|
|
type: string
|
|
enum:
|
|
- active
|
|
- revoked
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
last_used_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
required:
|
|
- id
|
|
- label
|
|
- permissions_users
|
|
- status
|
|
- created_at
|
|
AdminApiKeyListResponse:
|
|
type: object
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/AdminApiKey"
|
|
required:
|
|
- items
|
|
PermissionsAuditResponse:
|
|
type: object
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/PermissionsAuditItem"
|
|
required:
|
|
- items
|
|
PermissionsAuditItem:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
api_key_id:
|
|
type: string
|
|
permissions_users:
|
|
type: array
|
|
items:
|
|
type: string
|
|
requested_at:
|
|
type: string
|
|
format: date-time
|
|
endpoint:
|
|
type: string
|
|
remote_addr:
|
|
type: string
|
|
nullable: true
|
|
user_agent:
|
|
type: string
|
|
nullable: true
|
|
provided_permissions:
|
|
type: object
|
|
additionalProperties: true
|
|
provided_metadata:
|
|
type: object
|
|
additionalProperties: true
|
|
required:
|
|
- id
|
|
- api_key_id
|
|
- permissions_users
|
|
- requested_at
|
|
- endpoint
|
|
- provided_permissions
|
|
- provided_metadata
|
|
AdminApiKeyCreateRequest:
|
|
type: object
|
|
properties:
|
|
label:
|
|
type: string
|
|
permissions_users:
|
|
type: array
|
|
items:
|
|
type: string
|
|
required:
|
|
- label
|
|
- permissions_users
|
|
AdminApiKeyCreateResponse:
|
|
type: object
|
|
properties:
|
|
api_key:
|
|
type: string
|
|
description: Returned only once on creation
|
|
key:
|
|
$ref: "#/components/schemas/AdminApiKey"
|
|
required:
|
|
- api_key
|
|
- key
|
|
AdminApiKeyUpdateRequest:
|
|
type: object
|
|
properties:
|
|
label:
|
|
type: string
|
|
permissions_users:
|
|
type: array
|
|
items:
|
|
type: string
|
|
ErrorResponse:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
code:
|
|
type: string
|
|
required:
|
|
- error
|