chore: import upstream snapshot with attribution
Lint and Format Check / lint-and-format (push) Failing after 0s
Check Migrations / Check for duplicate migration numbers (push) Failing after 1s
CI Pre-merge Check / CI Pre-merge Check (push) Failing after 2m17s

This commit is contained in:
wehub-resource-sync
2026-07-13 12:23:40 +08:00
commit 3a28426bf4
1399 changed files with 257375 additions and 0 deletions
+686
View File
@@ -0,0 +1,686 @@
openapi: 3.0.3
info:
title: Insforge AI API
version: 1.0.0
description: Model Gateway helper APIs for OpenRouter key provisioning, model discovery, and deprecated compatibility proxy routes
paths:
/api/ai/models:
get:
summary: Get all available AI models
description: Returns the normalized OpenRouter model catalog fetched from OpenRouter with output_modalities=all.
tags:
- Admin
security:
- bearerAuth: []
responses:
'200':
description: Flat array of available models from the OpenRouter catalog
content:
application/json:
schema:
$ref: '#/components/schemas/ListModelsResponse'
'401':
description: Unauthorized
'500':
description: Failed to get models list
/api/ai/overview:
get:
summary: Get Model Gateway overview
description: Returns key-level OpenRouter usage and activity time series when the key has activity access.
tags:
- Admin
security:
- bearerAuth: []
responses:
'200':
description: Model Gateway overview
content:
application/json:
schema:
$ref: '#/components/schemas/AIOverview'
'401':
description: Unauthorized
'500':
description: Failed to fetch overview
/api/ai/openrouter/api-key:
get:
summary: Get active OpenRouter API key
description: Returns the active OpenRouter API key details for admin copy workflows.
tags:
- Admin
security:
- bearerAuth: []
responses:
'200':
description: Active OpenRouter API key details
content:
application/json:
schema:
$ref: '#/components/schemas/OpenRouterKeyResponse'
'400':
description: Missing OpenRouter API key
'401':
description: Unauthorized
'500':
description: Failed to fetch API key details
/api/ai/chat/completion:
post:
summary: Generate chat completion (deprecated)
deprecated: true
description: Deprecated compatibility proxy. New integrations should call https://openrouter.ai/api/v1/chat/completions directly with the provisioned OpenRouter key.
tags:
- Client
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ChatRequest'
responses:
'200':
description: Chat completion response
content:
application/json:
schema:
$ref: '#/components/schemas/ChatCompletionResponse'
text/event-stream:
schema:
type: string
description: Server-sent events stream for streaming responses
'400':
description: Invalid request - missing model or messages
'401':
description: Unauthorized
'500':
description: Failed to get response
/api/ai/image/generation:
post:
summary: Generate images (deprecated)
deprecated: true
description: Deprecated compatibility proxy. New integrations should use OpenRouter image-capable models directly with the provisioned OpenRouter key.
tags:
- Client
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ImageGenerationOptions'
responses:
'200':
description: Images generated successfully
content:
application/json:
schema:
type: object
properties:
model:
type: string
description: Model used for generation
images:
type: array
items:
$ref: '#/components/schemas/OpenRouterImageMessage'
text:
type: string
description: Text content from multimodal models
count:
type: integer
description: Number of images generated
metadata:
type: object
properties:
model:
type: string
revisedPrompt:
type: string
usage:
$ref: '#/components/schemas/TokenUsage'
nextActions:
type: string
example: Images have been generated successfully. Use the returned URLs or base64 data to access them.
'400':
description: Invalid request - missing model or prompt
'401':
description: Unauthorized
'500':
description: Failed to generate image
/api/ai/embeddings:
post:
summary: Generate embeddings (deprecated)
deprecated: true
description: Deprecated compatibility proxy. New integrations should call https://openrouter.ai/api/v1/embeddings directly with the provisioned OpenRouter key.
tags:
- Client
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/EmbeddingsRequest'
responses:
'200':
description: Embeddings generated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/EmbeddingsResponse'
'400':
description: Invalid request - missing model or input
'401':
description: Unauthorized
'500':
description: Failed to generate embeddings
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
ChatMessage:
type: object
required:
- role
properties:
role:
type: string
enum: [user, assistant, system, tool]
description: Role of the message sender
content:
type: string
nullable: true
description: Message content (nullable for assistant messages with tool_calls)
tool_calls:
type: array
description: Tool calls made by the assistant (assistant messages only)
items:
$ref: '#/components/schemas/ToolCall'
tool_call_id:
type: string
description: ID of the tool call being responded to (tool messages only)
ChatRequest:
type: object
required:
- model
- messages
properties:
model:
type: string
description: OpenRouter model identifier
example: openai/gpt-4
messages:
type: array
description: Array of messages for conversation (supports text, images, audio, and files/PDFs)
items:
$ref: '#/components/schemas/ChatMessage'
stream:
type: boolean
default: false
description: Enable streaming response via Server-Sent Events
temperature:
type: number
minimum: 0
maximum: 2
description: Controls randomness in generation
maxTokens:
type: integer
description: Maximum number of tokens to generate
topP:
type: number
minimum: 0
maximum: 1
description: Nucleus sampling parameter
webSearch:
$ref: '#/components/schemas/WebSearchPlugin'
fileParser:
$ref: '#/components/schemas/FileParserPlugin'
thinking:
type: boolean
description: Enable extended reasoning capabilities (appends :thinking to model ID if not already present). Not every model supports this, only works with Anthropic models with the :thinking suffix.
tools:
type: array
description: Tool definitions for function calling
items:
$ref: '#/components/schemas/Tool'
toolChoice:
description: 'Controls tool usage: auto, none, required, or a specific function'
oneOf:
- type: string
enum: [auto, none, required]
- type: object
required:
- type
- function
properties:
type:
type: string
enum: [function]
function:
type: object
required:
- name
properties:
name:
type: string
parallelToolCalls:
type: boolean
description: Allow the model to call multiple tools in parallel
ChatCompletionResponse:
type: object
properties:
text:
type: string
description: AI model response content
tool_calls:
type: array
description: Tool calls requested by the model (present when the model invokes tools)
items:
$ref: '#/components/schemas/ToolCall'
annotations:
type: array
description: URL citations from web search results (present when webSearch is enabled)
items:
$ref: '#/components/schemas/UrlCitationAnnotation'
metadata:
type: object
properties:
model:
type: string
usage:
$ref: '#/components/schemas/TokenUsage'
TokenUsage:
type: object
properties:
promptTokens:
type: integer
completionTokens:
type: integer
totalTokens:
type: integer
WebSearchPlugin:
type: object
required:
- enabled
properties:
enabled:
type: boolean
description: Enable web search integration
engine:
type: string
enum: [native, exa]
description: |
Search engine selection:
- native: Use provider's built-in web search (OpenAI, Anthropic, Perplexity, xAI)
- exa: Use Exa's search API
- undefined: Auto-select (native if available, otherwise Exa)
maxResults:
type: integer
minimum: 1
maximum: 10
default: 5
description: Maximum number of search results to include
searchPrompt:
type: string
description: Custom prompt for attaching search results to the message
FileParserPlugin:
type: object
required:
- enabled
properties:
enabled:
type: boolean
description: Enable file parsing for PDFs in messages
pdf:
type: object
properties:
engine:
type: string
enum: [pdf-text, mistral-ocr, native]
description: |
PDF processing engine:
- pdf-text: Best for well-structured PDFs with clear text content (Free)
- mistral-ocr: Best for scanned documents or PDFs with images ($2 per 1,000 pages)
- native: Only for models with native file support (charged as input tokens)
If not specified, defaults to native if available, otherwise mistral-ocr
Tool:
type: object
required:
- type
- function
properties:
type:
type: string
enum: [function]
function:
$ref: '#/components/schemas/FunctionDefinition'
FunctionDefinition:
type: object
required:
- name
properties:
name:
type: string
description: The name of the function to call
description:
type: string
description: A description of what the function does
parameters:
type: object
description: JSON Schema describing the function parameters
ToolCall:
type: object
required:
- id
- type
- function
properties:
id:
type: string
description: Unique identifier for this tool call
type:
type: string
enum: [function]
function:
type: object
required:
- name
- arguments
properties:
name:
type: string
description: The name of the function called
arguments:
type: string
description: JSON string of the function arguments
FileContent:
type: object
description: File content for PDFs and other documents
required:
- type
- file
properties:
type:
type: string
enum: [file]
file:
type: object
required:
- filename
- file_data
properties:
filename:
type: string
description: Filename with extension (e.g., "document.pdf")
example: document.pdf
file_data:
type: string
description: |
File data can be:
- Public URL: "https://example.com/document.pdf"
- Base64 data URL: "data:application/pdf;base64,..."
example: "https://example.com/document.pdf"
UrlCitationAnnotation:
type: object
properties:
type:
type: string
enum: [url_citation]
urlCitation:
type: object
properties:
url:
type: string
description: URL of the cited source
title:
type: string
description: Title of the cited page
content:
type: string
description: Relevant content snippet from the source
startIndex:
type: integer
description: Start character index in response text where citation applies
endIndex:
type: integer
description: End character index in response text where citation applies
ImageGenerationOptions:
type: object
required:
- model
- prompt
properties:
model:
type: string
description: OpenRouter model identifier for image generation
example: openai/dall-e-3
prompt:
type: string
description: Text prompt describing the desired image
example: "A serene landscape with mountains and a lake at sunset"
OpenRouterImageMessage:
type: object
properties:
type:
type: string
enum: [image_url]
image_url:
type: object
properties:
url:
type: string
description: Can be a direct URL or data:image base64 URL
ListModelsResponse:
type: array
description: Normalized OpenRouter model catalog returned by GET /api/ai/models.
items:
$ref: '#/components/schemas/AIModel'
AIModel:
type: object
properties:
id:
type: string
example: openai/gpt-4o
created:
type: integer
inputModality:
type: array
items:
type: string
example: [text, image]
outputModality:
type: array
items:
type: string
example: [text]
provider:
type: string
example: openrouter
modelId:
type: string
example: openai/gpt-4o
inputPrice:
type: number
description: Input price per million tokens in USD when token pricing is available.
outputPrice:
type: number
description: Output price per million tokens in USD when token pricing is available.
inputPriceLabel:
type: string
description: Human-readable input pricing label, such as "$2.50 / 1M tokens" or "Free", when available.
outputPriceLabel:
type: string
description: Human-readable output pricing label, such as "$10.00 / 1M tokens" or "Free", when available.
OpenRouterKeyResponse:
type: object
properties:
apiKey:
type: string
description: Active OpenRouter API key for admin copy workflows
maskedKey:
type: string
description: Masked OpenRouter API key for display
AIOverviewMetricPoint:
type: object
properties:
label:
type: string
value:
type: number
AIOverview:
type: object
properties:
key:
type: object
properties:
label:
type: string
limit:
type: number
nullable: true
limitRemaining:
type: number
nullable: true
limitReset:
type: string
nullable: true
usage:
type: number
usageDaily:
type: number
usageWeekly:
type: number
usageMonthly:
type: number
isFreeTier:
type: boolean
observabilityAvailable:
type: boolean
observabilityError:
type: string
charts:
type: object
properties:
spend:
type: array
items:
$ref: '#/components/schemas/AIOverviewMetricPoint'
requests:
type: array
items:
$ref: '#/components/schemas/AIOverviewMetricPoint'
tokens:
type: array
items:
$ref: '#/components/schemas/AIOverviewMetricPoint'
EmbeddingsRequest:
type: object
required:
- model
- input
properties:
model:
type: string
description: Embedding model identifier
example: google/gemini-embedding-001
input:
oneOf:
- type: string
description: Single text input to embed
- type: array
items:
type: string
description: Array of text inputs to embed
example: "Hello world"
encoding_format:
type: string
enum: [float, base64]
default: float
description: The format to return the embeddings in. Can be either float or base64.
dimensions:
type: integer
minimum: 0
description: The number of dimensions the resulting output embeddings should have. Only supported in certain models.
EmbeddingsResponse:
type: object
properties:
object:
type: string
enum: [list]
description: Object type, always "list"
data:
type: array
items:
$ref: '#/components/schemas/EmbeddingObject'
metadata:
type: object
properties:
model:
type: string
description: The model used for embedding
example: text-embedding-ada-002
usage:
$ref: '#/components/schemas/TokenUsage'
EmbeddingObject:
type: object
properties:
object:
type: string
enum: [embedding]
description: Object type, always "embedding"
embedding:
type: array
items:
type: number
description: The embedding vector (array of floats)
index:
type: integer
description: Index of this embedding in the input array
ErrorResponse:
type: object
required:
- error
properties:
error:
type: string
description: Error message
details:
type: string
description: Additional error details
code:
type: string
description: Error code for programmatic handling
+2068
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+158
View File
@@ -0,0 +1,158 @@
openapi: 3.0.3
info:
title: Insforge Email API
version: 1.0.0
description: Custom email sending endpoints for sending raw HTML emails
paths:
/api/email/send-raw:
post:
summary: Send raw HTML email
description: Send a custom HTML email to one or more recipients. Requires user authentication.
tags:
- Client
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SendRawEmailRequest'
responses:
'200':
description: Email sent successfully
content:
application/json:
schema:
$ref: '#/components/schemas/SendEmailResponse'
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized - requires authentication
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden - authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Email provider error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
SendRawEmailRequest:
type: object
required:
- to
- subject
- html
properties:
to:
oneOf:
- type: string
format: email
description: Single recipient email address
example: user@example.com
- type: array
items:
type: string
format: email
minItems: 1
maxItems: 50
description: Multiple recipient email addresses (max 50)
example: ["user1@example.com", "user2@example.com"]
description: Recipient email address(es) - maximum 50 recipients
subject:
type: string
minLength: 1
maxLength: 500
description: Email subject line
example: "Welcome to our platform"
html:
type: string
minLength: 1
description: HTML content of the email body
example: "<h1>Welcome!</h1><p>Thank you for joining us.</p>"
cc:
oneOf:
- type: string
format: email
description: Single CC recipient email address
- type: array
items:
type: string
format: email
minItems: 1
maxItems: 50
description: Multiple CC recipient email addresses (max 50)
description: Carbon copy recipient(s) - maximum 50 recipients
bcc:
oneOf:
- type: string
format: email
description: Single BCC recipient email address
- type: array
items:
type: string
format: email
minItems: 1
maxItems: 50
description: Multiple BCC recipient email addresses (max 50)
description: Blind carbon copy recipient(s) - maximum 50 recipients
from:
type: string
maxLength: 100
description: Custom sender name (uses default if not provided)
example: "My App"
replyTo:
type: string
format: email
description: Reply-to email address
example: "support@example.com"
SendEmailResponse:
type: object
description: Empty object on success - extend with optional fields later if needed
ErrorResponse:
type: object
required:
- error
- message
- statusCode
properties:
error:
type: string
description: Error code for programmatic handling
example: "VALIDATION_ERROR"
message:
type: string
description: Human-readable error message
example: "Subject is required"
statusCode:
type: integer
description: HTTP status code
example: 400
nextActions:
type: string
description: Suggested action to resolve the error
example: "Please provide a valid subject line"
+617
View File
@@ -0,0 +1,617 @@
openapi: 3.0.3
info:
title: Insforge Functions API
version: 1.0.0
description: Serverless functions running in Deno runtime
paths:
/api/functions:
get:
summary: List all functions
description: Get all functions with their metadata
tags:
- Admin
security:
- bearerAuth: []
responses:
'200':
description: List of functions
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/FunctionMetadata'
example:
- id: "123e4567-e89b-12d3-a456-426614174000"
slug: "hello-world"
name: "Hello World Function"
description: "Returns a greeting message"
status: "active"
created_at: "2024-01-21T10:30:00Z"
updated_at: "2024-01-21T10:35:00Z"
deployed_at: "2024-01-21T10:35:00Z"
- id: "223e4567-e89b-12d3-a456-426614174001"
slug: "process-webhook"
name: "Webhook Processor"
description: "Processes incoming webhooks"
status: "draft"
created_at: "2024-01-22T14:20:00Z"
updated_at: "2024-01-22T14:20:00Z"
deployed_at: null
'401':
description: Unauthorized
'403':
description: Forbidden - Admin only
'500':
description: Failed to list functions
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
post:
summary: Create new function
description: Create a new function with code that runs in Deno runtime
tags:
- Admin
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- name
- code
properties:
name:
type: string
minLength: 1
description: Display name for the function
example: "Hello World Function"
slug:
type: string
pattern: '^[a-zA-Z0-9_-]+$'
description: URL-friendly identifier (auto-generated from name if not provided)
example: "hello-world"
code:
type: string
minLength: 1
description: JavaScript/TypeScript code that exports an async function
example: |
export default async function(request) {
const { name = 'World' } = await request.json();
return new Response(
JSON.stringify({ message: `Hello, ${name}!` }),
{ headers: { 'Content-Type': 'application/json' } }
);
}
description:
type: string
description: Description of what the function does
example: "Returns a personalized greeting message"
status:
type: string
enum: ["draft", "active"]
default: "active"
description: Initial status (draft or active/deployed)
responses:
'201':
description: Function created successfully
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
function:
$ref: '#/components/schemas/FunctionMetadata'
example:
success: true
function:
id: "123e4567-e89b-12d3-a456-426614174000"
slug: "hello-world"
name: "Hello World Function"
description: "Returns a greeting message"
status: "active"
created_at: "2024-01-21T10:30:00Z"
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
examples:
validation:
value:
error: "Invalid request"
details:
- code: "too_small"
minimum: 1
path: ["name"]
message: "Name is required"
dangerousCode:
value:
error: "Code contains potentially dangerous patterns"
pattern: "/Deno\\.run/i"
'409':
description: Function slug already exists
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "Function with this slug already exists"
details: "duplicate key value violates unique constraint"
'500':
description: Failed to create function
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/functions/{slug}:
get:
summary: Get function details
description: Get a specific function including its code
tags:
- Admin
security:
- bearerAuth: []
parameters:
- name: slug
in: path
required: true
schema:
type: string
pattern: '^[a-zA-Z0-9_-]+$'
description: Function slug identifier
example: "hello-world"
responses:
'200':
description: Function details with code
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionDetails'
example:
id: "123e4567-e89b-12d3-a456-426614174000"
slug: "hello-world"
name: "Hello World Function"
description: "Returns a greeting message"
code: |
export default async function(request) {
const { name = 'World' } = await request.json();
return new Response(
JSON.stringify({ message: `Hello, ${name}!` }),
{ headers: { 'Content-Type': 'application/json' } }
);
}
status: "active"
created_at: "2024-01-21T10:30:00Z"
updated_at: "2024-01-21T10:35:00Z"
deployed_at: "2024-01-21T10:35:00Z"
'404':
description: Function not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "Function not found"
'401':
description: Unauthorized
'403':
description: Forbidden - Admin only
'500':
description: Failed to get function
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
put:
summary: Update function
description: Update an existing function's code or metadata
tags:
- Admin
security:
- bearerAuth: []
parameters:
- name: slug
in: path
required: true
schema:
type: string
pattern: '^[a-zA-Z0-9_-]+$'
description: Function slug identifier
example: "hello-world"
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: New display name
code:
type: string
description: Updated function code
description:
type: string
description: Updated description
status:
type: string
enum: ["draft", "active", "error"]
description: Function status
responses:
'200':
description: Function updated successfully
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
function:
$ref: '#/components/schemas/FunctionMetadata'
example:
success: true
function:
id: "123e4567-e89b-12d3-a456-426614174000"
slug: "hello-world"
name: "Hello World Function v2"
description: "Returns a greeting message"
status: "active"
updated_at: "2024-01-21T11:00:00Z"
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Function not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "Function not found"
'500':
description: Failed to update function
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
summary: Delete function
description: Permanently delete a function
tags:
- Admin
security:
- bearerAuth: []
parameters:
- name: slug
in: path
required: true
schema:
type: string
pattern: '^[a-zA-Z0-9_-]+$'
description: Function slug identifier
example: "hello-world"
responses:
'200':
description: Function deleted successfully
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
message:
type: string
example:
success: true
message: "Function hello-world deleted successfully"
'404':
description: Function not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "Function not found"
'500':
description: Failed to delete function
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/functions/{slug}:
get:
summary: Execute function (GET)
description: Execute a function using GET method. Proxied to Deno runtime.
tags:
- Client
parameters:
- name: slug
in: path
required: true
schema:
type: string
pattern: '^[a-zA-Z0-9_-]+$'
description: Function slug identifier
example: "hello-world"
responses:
'200':
description: Function executed successfully
content:
'*/*':
schema:
type: object
additionalProperties: true
example:
message: "Hello, World!"
'404':
description: Function not found or not active
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "Function not found or not active"
'502':
description: Failed to proxy to Deno runtime
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "Failed to connect to Deno runtime"
post:
summary: Execute function (POST)
description: Execute a function using POST method with JSON body. Proxied to Deno runtime.
tags:
- Client
parameters:
- name: slug
in: path
required: true
schema:
type: string
pattern: '^[a-zA-Z0-9_-]+$'
description: Function slug identifier
example: "hello-world"
requestBody:
required: false
content:
application/json:
schema:
type: object
additionalProperties: true
example:
name: "John"
age: 30
responses:
'200':
description: Function executed successfully
content:
'*/*':
schema:
type: object
additionalProperties: true
example:
message: "Hello, John!"
'404':
description: Function not found or not active
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "Function not found or not active"
'502':
description: Failed to proxy to Deno runtime
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "Failed to connect to Deno runtime"
put:
summary: Execute function (PUT)
description: Execute a function using PUT method. Proxied to Deno runtime.
tags:
- Client
parameters:
- name: slug
in: path
required: true
schema:
type: string
pattern: '^[a-zA-Z0-9_-]+$'
description: Function slug identifier
example: "hello-world"
requestBody:
required: false
content:
application/json:
schema:
type: object
additionalProperties: true
responses:
'200':
description: Function executed successfully
content:
'*/*':
schema:
type: object
additionalProperties: true
'502':
description: Failed to proxy to Deno runtime
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
patch:
summary: Execute function (PATCH)
description: Execute a function using PATCH method. Proxied to Deno runtime.
tags:
- Client
parameters:
- name: slug
in: path
required: true
schema:
type: string
pattern: '^[a-zA-Z0-9_-]+$'
description: Function slug identifier
example: "hello-world"
requestBody:
required: false
content:
application/json:
schema:
type: object
additionalProperties: true
responses:
'200':
description: Function executed successfully
content:
'*/*':
schema:
type: object
additionalProperties: true
'502':
description: Failed to proxy to Deno runtime
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
summary: Execute function (DELETE)
description: Execute a function using DELETE method. Proxied to Deno runtime.
tags:
- Client
parameters:
- name: slug
in: path
required: true
schema:
type: string
pattern: '^[a-zA-Z0-9_-]+$'
description: Function slug identifier
example: "hello-world"
responses:
'200':
description: Function executed successfully
content:
'*/*':
schema:
type: object
additionalProperties: true
'502':
description: Failed to proxy to Deno runtime
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
FunctionMetadata:
type: object
properties:
id:
type: string
format: uuid
description: Unique identifier for the function
slug:
type: string
description: URL-friendly identifier
example: "hello-world"
name:
type: string
description: Display name for the function
example: "Hello World Function"
description:
type: string
nullable: true
description: Description of what the function does
status:
type: string
enum: ["draft", "active", "error"]
description: Current status of the function
created_at:
type: string
format: date-time
description: When the function was created
updated_at:
type: string
format: date-time
description: When the function was last updated
deployed_at:
type: string
format: date-time
nullable: true
description: When the function was last deployed (null if never deployed)
required:
- id
- slug
- name
- status
- created_at
- updated_at
FunctionDetails:
allOf:
- $ref: '#/components/schemas/FunctionMetadata'
- type: object
properties:
code:
type: string
description: The function's JavaScript/TypeScript code
required:
- code
ErrorResponse:
type: object
properties:
error:
type: string
description: Error message
details:
oneOf:
- type: string
- type: array
items:
type: object
- type: object
description: Additional error details
message:
type: string
description: Detailed error message
pattern:
type: string
description: Pattern that caused validation failure (for dangerous code detection)
+30
View File
@@ -0,0 +1,30 @@
openapi: 3.0.3
info:
title: Insforge Health API
version: 1.0.0
paths:
/api/health:
get:
summary: Health check
description: Check if the API is running and healthy
tags:
- Client
responses:
'200':
description: API is healthy
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: ok
service:
type: string
example: Insforge Backend
timestamp:
type: string
format: date-time
example: "2025-01-21T03:45:22.194Z"
+222
View File
@@ -0,0 +1,222 @@
openapi: 3.0.3
info:
title: Insforge Logs API
version: 1.0.0
paths:
/api/logs:
get:
summary: List activity logs
tags:
- Admin
security:
- bearerAuth: []
parameters:
- name: limit
in: query
schema:
type: integer
default: 100
- name: offset
in: query
schema:
type: integer
default: 0
- name: action
in: query
schema:
type: string
enum: [INSERT, UPDATE, DELETE, LOGIN]
description: Filter by action type
- name: table
in: query
schema:
type: string
responses:
'200':
description: List of logs with pagination
headers:
X-Total-Count:
schema:
type: integer
description: Total number of logs
X-Page:
schema:
type: integer
description: Current page number
X-Page-Size:
schema:
type: integer
description: Number of items per page
X-Total-Pages:
schema:
type: integer
description: Total number of pages
content:
application/json:
schema:
type: array
items:
type: object
properties:
id:
type: string
timestamp:
type: string
format: date-time
action:
type: string
enum: [INSERT, UPDATE, DELETE, LOGIN]
table:
type: string
nullable: true
record_id:
type: string
nullable: true
user_id:
type: string
details:
type: object
nullable: true
example:
- id: "log-123"
timestamp: "2024-01-21T10:30:00Z"
action: "INSERT"
table: "posts"
record_id: "post-456"
user_id: "user-789"
details:
title: "New Post"
author: "John Doe"
- id: "log-124"
timestamp: "2024-01-21T10:31:00Z"
action: "LOGIN"
table: null
record_id: null
user_id: "user-789"
details:
ip: "192.168.1.1"
user_agent: "Mozilla/5.0..."
delete:
summary: Clear logs
tags:
- Admin
security:
- bearerAuth: []
parameters:
- name: before
in: query
schema:
type: string
format: date-time
responses:
'200':
description: Logs cleared
content:
application/json:
schema:
type: object
properties:
message:
type: string
deleted_count:
type: integer
example:
message: "Logs cleared successfully"
deleted_count: 150
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "INVALID_DATE"
message: "Invalid date format for 'before' parameter"
statusCode: 400
nextAction: "Use ISO 8601 date format (YYYY-MM-DDTHH:mm:ssZ)"
/api/logs/stats:
get:
summary: Get logs statistics
tags:
- Admin
security:
- bearerAuth: []
responses:
'200':
description: Logs statistics
content:
application/json:
schema:
type: object
properties:
actionStats:
type: array
items:
type: object
properties:
action:
type: string
count:
type: integer
tableStats:
type: array
items:
type: object
properties:
table_name:
type: string
count:
type: integer
recentActivity:
type: integer
description: Count of logs in last 24 hours
totalLogs:
type: integer
description: Total number of logs
example:
actionStats:
- action: "INSERT"
count: 245
- action: "UPDATE"
count: 189
- action: "DELETE"
count: 34
- action: "LOGIN"
count: 567
tableStats:
- table_name: "posts"
count: 156
- table_name: "comments"
count: 223
recentActivity: 47
totalLogs: 1035
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
schemas:
ErrorResponse:
type: object
required:
- error
- message
- statusCode
properties:
error:
type: string
description: Error code for programmatic handling
message:
type: string
description: Human-readable error message
statusCode:
type: integer
description: HTTP status code
nextAction:
type: string
description: Suggested action to resolve the error
+326
View File
@@ -0,0 +1,326 @@
openapi: 3.0.3
info:
title: Insforge Metadata API
version: 1.0.0
paths:
/api/metadata:
get:
summary: Get app metadata
description: >-
Returns aggregated application metadata (auth, database, storage,
functions, realtime, deployments). Use the `format` query parameter
to choose between JSON and Markdown output.
tags:
- Admin
security:
- bearerAuth: []
- apiKey: []
parameters:
- in: query
name: format
schema:
type: string
enum: [json, markdown]
default: json
description: >-
Response format. `json` returns structured JSON (default).
`markdown` returns a human-readable Markdown document suitable
for AI coding tools and developer onboarding.
responses:
'200':
description: Application metadata
content:
application/json:
schema:
type: object
properties:
auth:
type: object
properties:
oAuthProviders:
type: array
items:
type: string
requireEmailVerification:
type: boolean
disableSignup:
type: boolean
database:
type: object
properties:
tables:
type: array
items:
type: object
properties:
tableName:
type: string
recordCount:
type: integer
totalSizeInGB:
type: number
hint:
type: string
storage:
type: object
properties:
buckets:
type: array
items:
type: object
properties:
name:
type: string
public:
type: boolean
objectCount:
type: integer
totalSizeInGB:
type: number
functions:
type: array
items:
type: object
properties:
slug:
type: string
name:
type: string
status:
type: string
description:
type: string
realtime:
type: object
description: Optional; present when realtime is configured
properties:
channels:
type: array
items:
type: object
properties:
id:
type: string
pattern:
type: string
deployments:
type: object
description: Optional; present on cloud-hosted projects only
properties:
customSlug:
type: string
nullable: true
version:
type: string
example:
auth:
oAuthProviders: ["google", "github"]
requireEmailVerification: true
disableSignup: false
database:
tables:
- tableName: "users"
recordCount: 150
- tableName: "posts"
recordCount: 1200
totalSizeInGB: 0.3
storage:
buckets:
- name: "avatars"
public: true
objectCount: 42
totalSizeInGB: 0.5
functions:
- slug: "hello-world"
name: "hello-world"
status: "active"
description: "Test function"
version: "2.0.0"
text/markdown:
schema:
type: string
example: |
# Project Metadata
> v2.0.0
## Auth
- **OAuth providers**: google, github
- **Email verification**: required
- **Signup**: enabled
'400':
description: Invalid format parameter
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized — missing or invalid credentials
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden — authenticated but not an admin
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/metadata/database:
get:
summary: Get database metadata
description: Get database statistics and table information for dashboard
tags:
- Admin
security:
- bearerAuth: []
- apiKey: []
responses:
'200':
description: Database metadata
content:
application/json:
schema:
type: object
properties:
tables:
type: array
items:
type: object
properties:
name:
type: string
recordCount:
type: integer
totalTables:
type: integer
totalRecords:
type: integer
databaseSize:
type: string
lastUpdated:
type: string
format: date-time
example:
tables:
- name: "posts"
recordCount: 5678
- name: "comments"
recordCount: 9012
totalTables: 15
totalRecords: 16924
databaseSize: "125 MB"
lastUpdated: "2024-01-21T10:30:00Z"
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "UNAUTHORIZED"
message: "Invalid or missing authentication"
statusCode: 401
nextAction: "Please provide valid authentication credentials"
/api/metadata/api-key:
get:
summary: Get API key
description: Admin-only endpoint to retrieve the API key
tags:
- Admin
security:
- bearerAuth: []
responses:
'200':
description: API key
content:
application/json:
schema:
type: object
properties:
apiKey:
type: string
example:
apiKey: "ins_1234567890abcdef1234567890abcdef"
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "INSUFFICIENT_PERMISSIONS"
message: "Only admin users can access API keys"
statusCode: 403
nextAction: "Contact an administrator for API key access"
/api/metadata/anon-key:
get:
summary: Get anon key
description: >-
Admin-only endpoint to retrieve the project's opaque anon key
(`anon_...`). The anon key is a non-secret client identifier that maps
requests to the `anon` role - safe to embed in frontend bundles; row
level security is the security boundary. Rotatable via
POST /api/secrets/anon-key/rotate.
tags:
- Admin
security:
- bearerAuth: []
responses:
'200':
description: Anon key
content:
application/json:
schema:
type: object
properties:
anonKey:
type: string
example:
anonKey: "anon_1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcd"
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Anon key not initialized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
apiKey:
type: apiKey
in: header
name: X-API-Key
schemas:
ErrorResponse:
type: object
required:
- error
- message
- statusCode
properties:
error:
type: string
description: Error code for programmatic handling
message:
type: string
description: Human-readable error message
statusCode:
type: integer
description: HTTP status code
nextAction:
type: string
description: Suggested action to resolve the error
File diff suppressed because it is too large Load Diff
+833
View File
@@ -0,0 +1,833 @@
openapi: 3.0.3
info:
title: Insforge Realtime API
version: 1.0.0
description: Realtime channel management, message history, permissions, and retention API. Live pub/sub uses Socket.IO.
tags:
- name: Channels
description: Configure realtime channel patterns, webhooks, and availability.
- name: Messages
description: Inspect realtime message history and delivery stats.
- name: Permissions
description: Manage helper endpoints for realtime RLS examples.
- name: Configuration
description: Manage realtime retention settings.
paths:
/api/realtime/channels:
get:
summary: List All Channels
description: Retrieve all configured realtime channels
tags:
- Channels
security:
- bearerAuth: []
- apiKey: []
responses:
'200':
description: List of channels
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Channel'
example:
- id: "550e8400-e29b-41d4-a716-446655440000"
pattern: "order:%"
description: "Order updates channel"
webhookUrls: ["https://example.com/webhook"]
enabled: true
createdAt: "2024-01-15T10:30:00Z"
updatedAt: "2024-01-15T10:30:00Z"
- id: "550e8400-e29b-41d4-a716-446655440001"
pattern: "chat:%"
description: "Chat room messages"
webhookUrls: null
enabled: true
createdAt: "2024-01-16T11:00:00Z"
updatedAt: "2024-01-16T11:00:00Z"
post:
summary: Create Channel
description: Create a new realtime channel with a pattern for subscription matching
tags:
- Channels
security:
- bearerAuth: []
- apiKey: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateChannelRequest'
example:
pattern: "order:%"
description: "Order updates channel"
webhookUrls: ["https://example.com/webhook"]
enabled: true
responses:
'201':
description: Channel created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Channel'
example:
id: "550e8400-e29b-41d4-a716-446655440000"
pattern: "order:%"
description: "Order updates channel"
webhookUrls: ["https://example.com/webhook"]
enabled: true
createdAt: "2024-01-15T10:30:00Z"
updatedAt: "2024-01-15T10:30:00Z"
'400':
description: Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "INVALID_INPUT"
message: "pattern: Channel pattern is required"
statusCode: 400
/api/realtime/channels/{id}:
get:
summary: Get Channel by ID
description: Retrieve a specific channel by its UUID
tags:
- Channels
security:
- bearerAuth: []
- apiKey: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
example: "550e8400-e29b-41d4-a716-446655440000"
responses:
'200':
description: Channel details
content:
application/json:
schema:
$ref: '#/components/schemas/Channel'
example:
id: "550e8400-e29b-41d4-a716-446655440000"
pattern: "order:%"
description: "Order updates channel"
webhookUrls: ["https://example.com/webhook"]
enabled: true
createdAt: "2024-01-15T10:30:00Z"
updatedAt: "2024-01-15T10:30:00Z"
'404':
description: Channel not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "NOT_FOUND"
message: "Channel not found"
statusCode: 404
put:
summary: Update Channel
description: Update an existing channel's configuration
tags:
- Channels
security:
- bearerAuth: []
- apiKey: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
example: "550e8400-e29b-41d4-a716-446655440000"
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateChannelRequest'
example:
description: "Updated order channel description"
enabled: false
responses:
'200':
description: Channel updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Channel'
example:
id: "550e8400-e29b-41d4-a716-446655440000"
pattern: "order:%"
description: "Updated order channel description"
webhookUrls: ["https://example.com/webhook"]
enabled: false
createdAt: "2024-01-15T10:30:00Z"
updatedAt: "2024-01-17T14:00:00Z"
'400':
description: Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "INVALID_INPUT"
message: "webhookUrls.0: Invalid url"
statusCode: 400
'404':
description: Channel not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "NOT_FOUND"
message: "Channel not found"
statusCode: 404
delete:
summary: Delete Channel
description: Delete a channel definition. Existing message history is preserved with null channelId values.
tags:
- Channels
security:
- bearerAuth: []
- apiKey: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
example: "550e8400-e29b-41d4-a716-446655440000"
responses:
'200':
description: Channel deleted successfully
content:
application/json:
schema:
type: object
properties:
message:
type: string
example:
message: "Channel deleted"
'404':
description: Channel not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "NOT_FOUND"
message: "Channel not found"
statusCode: 404
/api/realtime/messages:
get:
summary: List Messages
description: Retrieve message history with optional filters
tags:
- Messages
security:
- bearerAuth: []
- apiKey: []
parameters:
- name: channelId
in: query
required: false
schema:
type: string
format: uuid
description: Filter messages by channel ID
example: "550e8400-e29b-41d4-a716-446655440000"
- name: eventName
in: query
required: false
schema:
type: string
description: Filter messages by event name
example: "order.created"
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 1000
default: 100
description: Maximum number of messages to return
- name: offset
in: query
required: false
schema:
type: integer
minimum: 0
default: 0
description: Number of messages to skip
responses:
'200':
description: List of messages
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Message'
example:
- id: "660e8400-e29b-41d4-a716-446655440000"
eventName: "order.created"
channelId: "550e8400-e29b-41d4-a716-446655440000"
channelName: "order:123"
payload:
orderId: "123"
status: "pending"
senderType: "user"
senderId: "770e8400-e29b-41d4-a716-446655440000"
wsAudienceCount: 5
whAudienceCount: 1
whDeliveredCount: 1
createdAt: "2024-01-15T10:30:00Z"
'400':
description: Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "INVALID_INPUT"
message: "channelId: Invalid uuid"
statusCode: 400
delete:
summary: Clear Messages
description: Permanently delete all stored realtime messages
tags:
- Messages
security:
- bearerAuth: []
- apiKey: []
responses:
'200':
description: Messages cleared
content:
application/json:
schema:
$ref: '#/components/schemas/ClearMessagesResponse'
example:
deleted: 42
/api/realtime/messages/stats:
get:
summary: Get Message Statistics
description: Retrieve aggregated statistics about messages
tags:
- Messages
security:
- bearerAuth: []
- apiKey: []
parameters:
- name: channelId
in: query
required: false
schema:
type: string
format: uuid
description: Filter stats by channel ID
example: "550e8400-e29b-41d4-a716-446655440000"
- name: since
in: query
required: false
schema:
type: string
format: date-time
description: Filter stats since this timestamp
example: "2024-01-01T00:00:00Z"
responses:
'200':
description: Message statistics
content:
application/json:
schema:
$ref: '#/components/schemas/MessageStats'
example:
totalMessages: 1250
whDeliveryRate: 0.98
topEvents:
- eventName: "order.created"
count: 450
- eventName: "order.updated"
count: 380
- eventName: "order.completed"
count: 220
retentionDays: null
'400':
description: Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "INVALID_INPUT"
message: "since: Invalid datetime"
statusCode: 400
/api/realtime/permissions:
get:
summary: Get Realtime Permissions
description: Retrieve RLS policies for subscribe (channels) and publish (messages) operations
tags:
- Permissions
security:
- bearerAuth: []
- apiKey: []
responses:
'200':
description: Realtime RLS permissions
content:
application/json:
schema:
$ref: '#/components/schemas/RealtimePermissions'
example:
subscribe:
policies:
- policyName: "allow_authenticated_subscribe"
tableName: "channels"
command: "SELECT"
roles: ["authenticated"]
using: "enabled = true"
withCheck: null
publish:
policies:
- policyName: "allow_authenticated_publish"
tableName: "messages"
command: "INSERT"
roles: ["authenticated"]
using: null
withCheck: "true"
/api/realtime/config:
get:
summary: Get Realtime Config
description: Retrieve realtime message retention configuration
tags:
- Configuration
security:
- bearerAuth: []
- apiKey: []
responses:
'200':
description: Realtime configuration
content:
application/json:
schema:
$ref: '#/components/schemas/RealtimeConfig'
example:
retentionDays: null
patch:
summary: Update Realtime Config
description: Update realtime message retention configuration
tags:
- Configuration
security:
- bearerAuth: []
- apiKey: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateRealtimeConfigRequest'
examples:
retainFor90Days:
value:
retentionDays: 90
keepForever:
value:
retentionDays: null
responses:
'200':
description: Realtime configuration updated
content:
application/json:
schema:
type: object
required:
- message
properties:
message:
type: string
example:
message: "Retention config updated successfully"
'400':
description: Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "INVALID_INPUT"
message: "retentionDays: Number must be greater than 0"
statusCode: 400
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
apiKey:
type: apiKey
in: header
name: X-API-Key
schemas:
Channel:
type: object
required:
- id
- pattern
- enabled
- createdAt
- updatedAt
properties:
id:
type: string
format: uuid
description: Unique identifier for the channel
example: "550e8400-e29b-41d4-a716-446655440000"
pattern:
type: string
minLength: 1
description: Channel pattern for subscription matching. Uses SQL LIKE wildcards, for example "order:%".
example: "order:%"
description:
type: string
nullable: true
description: Human-readable description of the channel
example: "Order updates channel"
webhookUrls:
type: array
nullable: true
items:
type: string
format: uri
description: URLs to receive webhook notifications for messages on this channel
example: ["https://example.com/webhook"]
enabled:
type: boolean
description: Whether the channel is currently active
example: true
createdAt:
type: string
format: date-time
description: Timestamp when the channel was created
example: "2024-01-15T10:30:00Z"
updatedAt:
type: string
format: date-time
description: Timestamp when the channel was last updated
example: "2024-01-15T10:30:00Z"
CreateChannelRequest:
type: object
required:
- pattern
properties:
pattern:
type: string
minLength: 1
description: Channel pattern for subscription matching. Uses SQL LIKE wildcards, for example "order:%".
example: "order:%"
description:
type: string
description: Human-readable description of the channel
example: "Order updates channel"
webhookUrls:
type: array
items:
type: string
format: uri
description: URLs to receive webhook notifications
example: ["https://example.com/webhook"]
enabled:
type: boolean
default: true
description: Whether the channel should be active upon creation
example: true
UpdateChannelRequest:
type: object
properties:
pattern:
type: string
minLength: 1
description: Updated channel pattern
example: "order:%"
description:
type: string
description: Updated description
example: "Updated order channel"
webhookUrls:
type: array
items:
type: string
format: uri
description: Updated webhook URLs
example: ["https://example.com/webhook"]
enabled:
type: boolean
description: Updated enabled status
example: false
Message:
type: object
required:
- id
- eventName
- channelName
- payload
- senderType
- wsAudienceCount
- whAudienceCount
- whDeliveredCount
- createdAt
properties:
id:
type: string
format: uuid
description: Unique identifier for the message
example: "660e8400-e29b-41d4-a716-446655440000"
eventName:
type: string
minLength: 1
description: Name of the event
example: "order.created"
channelId:
type: string
format: uuid
nullable: true
description: ID of the channel this message belongs to
example: "550e8400-e29b-41d4-a716-446655440000"
channelName:
type: string
minLength: 1
description: Resolved channel name (instance of the pattern)
example: "order:123"
payload:
type: object
additionalProperties: true
description: Message payload data
example:
orderId: "123"
status: "pending"
senderType:
type: string
enum: [system, user]
description: Type of sender that published the message
example: "user"
senderId:
type: string
format: uuid
nullable: true
description: ID of the user who sent the message (null for system messages)
example: "770e8400-e29b-41d4-a716-446655440000"
wsAudienceCount:
type: integer
minimum: 0
description: Number of WebSocket clients who received the message
example: 5
whAudienceCount:
type: integer
minimum: 0
description: Number of webhooks that should receive the message
example: 1
whDeliveredCount:
type: integer
minimum: 0
description: Number of webhooks that successfully received the message
example: 1
createdAt:
type: string
format: date-time
description: Timestamp when the message was created
example: "2024-01-15T10:30:00Z"
ClearMessagesResponse:
type: object
required:
- deleted
properties:
deleted:
type: integer
minimum: 0
description: Number of realtime messages deleted
example: 42
MessageStats:
type: object
required:
- totalMessages
- whDeliveryRate
- topEvents
- retentionDays
properties:
totalMessages:
type: integer
minimum: 0
description: Total number of messages
example: 1250
whDeliveryRate:
type: number
minimum: 0
maximum: 1
description: Webhook delivery success rate (0-1)
example: 0.98
topEvents:
type: array
description: Most frequent event types
items:
type: object
required:
- eventName
- count
properties:
eventName:
type: string
description: Name of the event
example: "order.created"
count:
type: integer
minimum: 0
description: Number of occurrences
example: 450
retentionDays:
type: integer
nullable: true
minimum: 1
description: Number of days messages are retained. Null means messages are kept indefinitely.
example: null
RealtimeConfig:
type: object
required:
- retentionDays
properties:
retentionDays:
type: integer
nullable: true
minimum: 1
description: Number of days messages are retained. Null means messages are kept indefinitely.
example: null
UpdateRealtimeConfigRequest:
type: object
required:
- retentionDays
properties:
retentionDays:
type: integer
nullable: true
minimum: 1
description: Number of days messages are retained. Null means messages are kept indefinitely.
example: 90
RlsPolicy:
type: object
required:
- policyName
- tableName
- command
- roles
properties:
policyName:
type: string
description: Name of the RLS policy
example: "allow_authenticated_subscribe"
tableName:
type: string
description: Table the policy applies to
example: "channels"
command:
type: string
description: SQL command the policy applies to (SELECT, INSERT, UPDATE, DELETE)
example: "SELECT"
roles:
type: array
items:
type: string
description: Database roles the policy applies to
example: ["authenticated"]
using:
type: string
nullable: true
description: USING clause for row-level filtering
example: "enabled = true"
withCheck:
type: string
nullable: true
description: WITH CHECK clause for row-level validation
example: null
RealtimePermissions:
type: object
required:
- subscribe
- publish
properties:
subscribe:
type: object
required:
- policies
properties:
policies:
type: array
description: RLS policies for channel subscriptions
items:
$ref: '#/components/schemas/RlsPolicy'
publish:
type: object
required:
- policies
properties:
policies:
type: array
description: RLS policies for message publishing
items:
$ref: '#/components/schemas/RlsPolicy'
ErrorResponse:
type: object
required:
- error
- message
- statusCode
properties:
error:
type: string
description: Error code for programmatic handling
example: "INVALID_INPUT"
message:
type: string
description: Human-readable error message
example: "Invalid request"
statusCode:
type: integer
description: HTTP status code
example: 400
nextActions:
type: string
description: Suggested action to resolve the error
example: "Check your request parameters"
+382
View File
@@ -0,0 +1,382 @@
openapi: 3.0.3
info:
title: Insforge Records API
version: 2.0.0
description: PostgREST-style database record operations
paths:
/api/database/records/{tableName}:
get:
summary: Query Records
description: Query records from a table with filtering, sorting, and pagination
tags:
- Client
security:
- bearerAuth: []
- apiKey: []
parameters:
- name: tableName
in: path
required: true
schema:
type: string
description: Name of the table to query
example: posts
- name: limit
in: query
schema:
type: integer
default: 100
minimum: 1
maximum: 1000
description: Maximum number of records to return
- name: offset
in: query
schema:
type: integer
default: 0
minimum: 0
description: Number of records to skip for pagination
- name: order
in: query
schema:
type: string
description: Sort order (e.g., "createdAt.desc", "name.asc")
example: createdAt.desc
- name: select
in: query
schema:
type: string
description: Comma-separated list of columns to return
example: id,title,content
# PostgREST-style filters
- name: field
in: query
schema:
type: string
description: Filter by field value (e.g., "?status=eq.active", "?age=gt.18")
example: status=eq.active
responses:
'200':
description: List of records
headers:
X-Total-Count:
schema:
type: integer
description: Total number of records matching the query
Content-Range:
schema:
type: string
description: Range of records returned (e.g., "0-99/1234")
content:
application/json:
schema:
type: array
items:
type: object
additionalProperties: true
example:
- id: "248373e1-0aea-45ce-8844-5ef259203749"
title: "Getting Started with InsForge"
content: "This is a guide to help you get started..."
createdAt: "2025-07-18T05:37:24.338Z"
updatedAt: "2025-07-18T05:37:24.338Z"
- id: "348373e1-0aea-45ce-8844-5ef259203750"
title: "Advanced Database Queries"
content: "Learn how to write complex queries..."
createdAt: "2025-07-19T08:15:10.123Z"
updatedAt: "2025-07-19T08:15:10.123Z"
'404':
description: Table not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "TABLE_NOT_FOUND"
message: "Table 'nonexistent' does not exist"
statusCode: 404
nextActions: "Check table name and try again"
'400':
description: Invalid query parameters
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "INVALID_QUERY"
message: "Invalid filter syntax"
statusCode: 400
nextActions: "Check PostgREST filter documentation"
post:
summary: Create Records
description: Create one or more records. Request body MUST be an array.
tags:
- Client
security:
- bearerAuth: []
- apiKey: []
parameters:
- name: tableName
in: path
required: true
schema:
type: string
description: Name of the table
example: posts
- name: Prefer
in: header
schema:
type: string
enum: ["return=representation"]
description: Include to return created records in response (otherwise returns empty array)
requestBody:
required: true
content:
application/json:
schema:
type: array
items:
type: object
additionalProperties: true
minItems: 1
example:
- title: "My First Post"
content: "Hello world! This is my first post."
published: true
responses:
'201':
description: Records created
content:
application/json:
schema:
type: array
items:
type: object
additionalProperties: true
examples:
without_prefer:
summary: Response without Prefer header
value: []
with_prefer:
summary: "Response with Prefer: return=representation"
value:
- id: "248373e1-0aea-45ce-8844-5ef259203749"
title: "My First Post"
content: "Hello world! This is my first post."
published: true
createdAt: "2025-07-18T05:37:24.338Z"
updatedAt: "2025-07-18T05:37:24.338Z"
'400':
description: Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "VALIDATION_ERROR"
message: "Invalid field type: expected boolean for 'published'"
statusCode: 400
nextActions: "Ensure field types match the table schema"
'404':
description: Table not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "TABLE_NOT_FOUND"
message: "Table 'nonexistent' does not exist"
statusCode: 404
nextActions: "Create the table first"
patch:
summary: Update Records
description: Update records matching query filters
tags:
- Client
security:
- bearerAuth: []
- apiKey: []
parameters:
- name: tableName
in: path
required: true
schema:
type: string
description: Name of the table
example: posts
- name: id
in: query
schema:
type: string
description: Filter records by ID (e.g., "?id=eq.123e4567-e89b-12d3-a456-426614174000")
example: eq.123e4567-e89b-12d3-a456-426614174000
- name: Prefer
in: header
schema:
type: string
enum: ["return=representation"]
description: Include to return updated records in response
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: true
example:
title: "Updated Post Title"
content: "This content has been updated."
responses:
'200':
description: Records updated
content:
application/json:
schema:
type: array
items:
type: object
additionalProperties: true
examples:
without_prefer:
summary: Response without Prefer header
value: []
with_prefer:
summary: "Response with Prefer: return=representation"
value:
- id: "123e4567-e89b-12d3-a456-426614174000"
title: "Updated Post Title"
content: "This content has been updated."
createdAt: "2025-01-01T00:00:00Z"
updatedAt: "2025-01-21T11:00:00Z"
'404':
description: No records found to update
content:
application/json:
schema:
type: array
items:
type: object
example: []
'400':
description: Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "VALIDATION_ERROR"
message: "Invalid field type"
statusCode: 400
nextActions: "Check field types match table schema"
delete:
summary: Delete Records
description: Delete records matching query filters
tags:
- Client
security:
- bearerAuth: []
- apiKey: []
parameters:
- name: tableName
in: path
required: true
schema:
type: string
description: Name of the table
example: posts
- name: id
in: query
schema:
type: string
description: Filter records by ID (e.g., "?id=eq.123e4567-e89b-12d3-a456-426614174000")
example: eq.123e4567-e89b-12d3-a456-426614174000
- name: Prefer
in: header
schema:
type: string
enum: ["return=representation"]
description: Include to return deleted records in response
responses:
'204':
description: Records deleted (without Prefer header)
'200':
description: Records deleted (with Prefer header)
content:
application/json:
schema:
type: array
items:
type: object
additionalProperties: true
examples:
records_deleted:
summary: Records were deleted
value:
- id: "123e4567-e89b-12d3-a456-426614174000"
title: "Deleted Post"
createdAt: "2025-01-01T00:00:00Z"
updatedAt: "2025-01-21T11:00:00Z"
no_records:
summary: No records found to delete
value: []
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
apiKey:
type: apiKey
in: header
name: x-api-key
schemas:
ErrorResponse:
type: object
required:
- error
- message
- statusCode
properties:
error:
type: string
description: Error code for programmatic handling
example: "VALIDATION_ERROR"
message:
type: string
description: Human-readable error message
example: "Invalid input data"
statusCode:
type: integer
description: HTTP status code
example: 400
nextActions:
type: string
description: Suggested action to resolve the error
example: "Check the request body format"
Record:
type: object
properties:
id:
type: string
format: uuid
description: Auto-generated UUID
createdAt:
type: string
format: date-time
description: Timestamp when record was created
updatedAt:
type: string
format: date-time
description: Timestamp when record was last updated
additionalProperties: true
description: Base record structure with system fields
security:
- bearerAuth: []
- apiKey: []
+433
View File
@@ -0,0 +1,433 @@
openapi: 3.0.3
info:
title: Insforge Secrets API
version: 1.0.0
description: Secure secrets management for storing API keys, tokens, and sensitive configuration
paths:
/api/secrets:
get:
summary: List all secrets
description: Returns metadata for all secrets (without values)
tags:
- Admin
security:
- bearerAuth: []
responses:
'200':
description: List of secret metadata
content:
application/json:
schema:
type: object
properties:
secrets:
type: array
items:
$ref: '#/components/schemas/SecretMetadata'
example:
secrets:
- id: "123e4567-e89b-12d3-a456-426614174000"
key: "STRIPE_API_KEY"
isActive: true
isReserved: false
createdAt: "2024-01-21T10:30:00Z"
updatedAt: "2024-01-21T10:30:00Z"
expiresAt: null
- id: "223e4567-e89b-12d3-a456-426614174001"
key: "OPENAI_API_KEY"
isActive: true
isReserved: true
createdAt: "2024-01-20T09:15:00Z"
updatedAt: "2024-01-20T09:15:00Z"
expiresAt: "2025-01-20T09:15:00Z"
'401':
description: Unauthorized
'403':
description: Forbidden - Admin only
post:
summary: Create a new secret
description: Create a new encrypted secret with a unique key
tags:
- Admin
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- key
- value
properties:
key:
type: string
pattern: '^[A-Z0-9_]+$'
description: Unique key identifier (uppercase letters, numbers, underscores only)
example: "STRIPE_API_KEY"
value:
type: string
description: Secret value to be encrypted
example: "sk_live_..."
isReserved:
type: boolean
default: false
description: Whether the secret is protected from deletion
expiresAt:
type: string
format: date-time
nullable: true
description: Optional expiration date for the secret
responses:
'201':
description: Secret created successfully
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
message:
type: string
id:
type: string
format: uuid
example:
success: true
message: "Secret STRIPE_API_KEY has been created successfully"
id: "123e4567-e89b-12d3-a456-426614174000"
'400':
description: Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
examples:
missingFields:
value:
error: "INVALID_INPUT"
message: "Both key and value are required"
statusCode: 400
invalidKeyFormat:
value:
error: "INVALID_INPUT"
message: "Invalid key format. Use uppercase letters, numbers, and underscores only (e.g., STRIPE_API_KEY)"
statusCode: 400
'409':
description: Secret already exists
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "INVALID_INPUT"
message: "Secret already exists: STRIPE_API_KEY"
statusCode: 409
/api/secrets/{key}:
get:
summary: Get secret value
description: Retrieve the decrypted value of a specific secret by its key
tags:
- Admin
security:
- bearerAuth: []
parameters:
- name: key
in: path
required: true
schema:
type: string
pattern: '^[A-Z0-9_]+$'
description: Secret key identifier
example: "STRIPE_API_KEY"
responses:
'200':
description: Secret value retrieved
content:
application/json:
schema:
type: object
properties:
key:
type: string
value:
type: string
example:
key: "STRIPE_API_KEY"
value: "sk_live_..."
'404':
description: Secret not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "NOT_FOUND"
message: "Secret not found: INVALID_KEY"
statusCode: 404
'401':
description: Unauthorized
'403':
description: Forbidden - Admin only
put:
summary: Update secret
description: Update an existing secret's value or metadata
tags:
- Admin
security:
- bearerAuth: []
parameters:
- name: key
in: path
required: true
schema:
type: string
pattern: '^[A-Z0-9_]+$'
description: Secret key identifier
example: "STRIPE_API_KEY"
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
value:
type: string
description: New secret value (will be encrypted)
isActive:
type: boolean
description: Whether the secret is active
isReserved:
type: boolean
description: Whether the secret is protected from deletion
expiresAt:
type: string
format: date-time
nullable: true
description: Expiration date (null to remove expiration)
responses:
'200':
description: Secret updated successfully
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
message:
type: string
example:
success: true
message: "Secret STRIPE_API_KEY has been updated successfully"
'404':
description: Secret not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "NOT_FOUND"
message: "Secret not found: INVALID_KEY"
statusCode: 404
'500':
description: Failed to update secret
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "INTERNAL_ERROR"
message: "Failed to update secret: STRIPE_API_KEY"
statusCode: 500
delete:
summary: Delete secret
description: Mark a secret as inactive (soft delete). Cannot delete reserved secrets.
tags:
- Admin
security:
- bearerAuth: []
parameters:
- name: key
in: path
required: true
schema:
type: string
pattern: '^[A-Z0-9_]+$'
description: Secret key identifier
example: "STRIPE_API_KEY"
responses:
'200':
description: Secret deleted successfully
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
message:
type: string
example:
success: true
message: "Secret STRIPE_API_KEY has been deleted successfully"
'403':
description: Cannot delete reserved secret
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "FORBIDDEN"
message: "Cannot delete reserved secret: OPENAI_API_KEY"
statusCode: 403
'404':
description: Secret not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "NOT_FOUND"
message: "Secret not found: INVALID_KEY"
statusCode: 404
/api/secrets/anon-key/rotate:
post:
summary: Rotate anon key
description: >-
Rotate the project's opaque anon key (`anon_...`). A new key is
generated and returned; the old key stays valid for the grace period
(default 168 hours / 7 days, max 720) so already-deployed frontends
and mobile binaries keep working while the new key ships. Admin only.
tags:
- Admin
security:
- bearerAuth: []
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
gracePeriodHours:
type: integer
minimum: 0
maximum: 720
default: 168
description: How long the old key remains valid after rotation
responses:
'200':
description: Anon key rotated successfully
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
message:
type: string
anonKey:
type: string
description: The new anon key
oldKeyExpiresAt:
type: string
format: date-time
description: When the previous key stops being accepted
example:
success: true
message: "Anon key rotated successfully. Old key will remain valid during grace period."
anonKey: "anon_1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcd"
oldKeyExpiresAt: "2026-06-18T00:00:00.000Z"
'400':
description: Invalid grace period
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden - admin access required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
SecretMetadata:
type: object
properties:
id:
type: string
format: uuid
description: Unique identifier for the secret
key:
type: string
description: Unique key identifier (uppercase with underscores)
example: "STRIPE_API_KEY"
isActive:
type: boolean
description: Whether the secret is currently active
isReserved:
type: boolean
description: Whether the secret is protected from deletion
createdAt:
type: string
format: date-time
description: When the secret was created
updatedAt:
type: string
format: date-time
description: When the secret was last updated
expiresAt:
type: string
format: date-time
nullable: true
description: When the secret expires (null if no expiration)
required:
- id
- key
- isActive
- isReserved
- createdAt
- updatedAt
ErrorResponse:
type: object
required:
- error
- message
- statusCode
properties:
error:
type: string
description: Error code for programmatic handling
example: "INVALID_INPUT"
message:
type: string
description: Human-readable error message
example: "Invalid input data"
statusCode:
type: integer
description: HTTP status code
example: 400
nextActions:
type: string
description: Suggested action to resolve the error
example: "Check the request body format"
+1372
View File
File diff suppressed because it is too large Load Diff
+604
View File
@@ -0,0 +1,604 @@
openapi: 3.0.3
info:
title: Insforge Tables API
version: 1.0.0
paths:
/api/database/tables:
get:
summary: List Tables
tags:
- Admin
security:
- bearerAuth: []
- apiKey: []
responses:
'200':
description: List of table names
content:
application/json:
schema:
type: array
items:
type: string
example:
- "posts"
- "comments"
- "categories"
post:
summary: Create Table
tags:
- Admin
security:
- bearerAuth: []
- apiKey: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- tableName
- columns
properties:
tableName:
type: string
columns:
type: array
items:
type: object
required:
- name
- type
- nullable
properties:
name:
type: string
type:
type: string
enum: [string, datetime, integer, float, boolean, uuid, json, file]
nullable:
type: boolean
unique:
type: boolean
defaultValue:
type: string
foreignKeys:
type: array
description: Table-level foreign key constraints
items:
$ref: '#/components/schemas/ForeignKeyConstraint'
rlsEnabled:
type: boolean
default: false
description: Enable Row Level Security on the table
responses:
'201':
description: Table created
content:
application/json:
schema:
type: object
properties:
message:
type: string
table_name:
type: string
example:
message: "Table created successfully"
tableName: "posts"
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "VALIDATION_ERROR"
message: "Table name already exists"
statusCode: 400
nextActions: "Choose a different table name"
'422':
description: Unprocessable entity
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "INVALID_FIELD_TYPE"
message: "Invalid field type: 'text'. Valid types are: string, integer, float, boolean, datetime, uuid, json, file"
statusCode: 422
nextActions: "Use one of the valid field types"
/api/database/tables/{tableName}/schema:
get:
summary: Get Table Schema
tags:
- Admin
security:
- bearerAuth: []
- apiKey: []
parameters:
- name: tableName
in: path
required: true
schema:
type: string
responses:
'200':
description: Table schema
content:
application/json:
schema:
type: object
properties:
table_name:
type: string
columns:
type: array
items:
type: object
properties:
name:
type: string
type:
type: string
nullable:
type: boolean
unique:
type: boolean
default:
type: string
nullable: true
isPrimaryKey:
type: boolean
foreignKeys:
type: array
description: Table-level foreign key constraints (one entry per constraint)
items:
$ref: '#/components/schemas/ForeignKeyConstraint'
example:
tableName: "posts"
columns:
- name: "id"
type: "uuid"
nullable: false
unique: true
default: "gen_random_uuid()"
isPrimaryKey: true
- name: "title"
type: "string"
nullable: false
unique: false
default: null
isPrimaryKey: false
- name: "userId"
type: "uuid"
nullable: false
unique: false
default: null
isPrimaryKey: false
foreignKeys:
- constraintName: "fk_userId_auth_users_id"
referenceTable: "auth.users"
referenceColumns:
- sourceColumn: "userId"
referenceColumn: "id"
onDelete: "CASCADE"
onUpdate: "CASCADE"
'404':
description: Table not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "TABLE_NOT_FOUND"
message: "Table 'nonexistent' does not exist"
statusCode: 404
nextActions: "Check table name and try again"
patch:
summary: Update Table Schema
tags:
- Admin
security:
- bearerAuth: []
- apiKey: []
parameters:
- name: tableName
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
addColumns:
type: array
description: Add new columns to the table
items:
type: object
required:
- columnName
- type
properties:
columnName:
type: string
description: Name of the new column
type:
type: string
enum: [string, integer, float, boolean, datetime, uuid, json, file]
description: Data type of the column
isNullable:
type: boolean
default: true
description: Whether the column allows NULL values
isUnique:
type: boolean
default: false
description: Whether the column values must be unique
defaultValue:
type: string
description: Default value for the column
dropColumns:
type: array
description: Remove columns from the table
items:
type: string
description: Name of the column to drop
updateColumns:
type: array
description: Modify existing columns (rename or change default)
items:
type: object
required:
- columnName
properties:
columnName:
type: string
description: Current name of the column
newColumnName:
type: string
description: New name for the column (optional)
minLength: 1
maxLength: 64
defaultValue:
type: string
description: New default value for the column (optional)
addForeignKeys:
type: array
description: Add foreign key constraints (one entry per constraint; composite keys list multiple column mappings)
items:
$ref: '#/components/schemas/ForeignKeyConstraint'
dropForeignKeys:
type: array
description: Constraint names of foreign keys to drop
items:
type: string
description: Name of the foreign key constraint to drop
renameTable:
type: object
description: Rename the table
required:
- newTableName
properties:
newTableName:
type: string
description: New name for the table
minLength: 1
maxLength: 64
responses:
'200':
description: Table schema updated successfully
content:
application/json:
schema:
type: object
properties:
message:
type: string
description: Success message
tableName:
type: string
description: Name of the updated table
operations:
type: array
description: List of operations performed
items:
type: string
example:
message: "Table schema updated successfully"
tableName: "posts"
operations:
- "added 2 columns"
- "dropped 1 columns"
- "renamed 1 columns"
- "added 1 foreign keys"
- "dropped 1 foreign keys"
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
examples:
columnExists:
value:
error: "COLUMN_EXISTS"
message: "Column 'title' already exists in table 'posts'"
statusCode: 400
nextActions: "Choose a different column name or drop it first"
columnNotFound:
value:
error: "COLUMN_NOT_FOUND"
message: "Column 'nonexistent' not found in table 'posts'"
statusCode: 400
nextActions: "Check column name with GET /api/tables/{tableName}/schema"
foreignKeyExists:
value:
error: "FOREIGN_KEY_EXISTS"
message: "Foreign key on column 'user_id' already exists"
statusCode: 400
nextActions: "Drop the existing foreign key first or use a different column"
'404':
description: Table not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "TABLE_NOT_FOUND"
message: "Table 'nonexistent' does not exist"
statusCode: 404
nextActions: "Check table name and try again"
/api/database/tables/{tableName}:
delete:
summary: Delete Table
tags:
- Admin
security:
- bearerAuth: []
- apiKey: []
parameters:
- name: tableName
in: path
required: true
schema:
type: string
responses:
'200':
description: Table deleted
content:
application/json:
schema:
type: object
properties:
message:
type: string
table_name:
type: string
example:
message: "Table deleted successfully"
tableName: "posts"
'404':
description: Table not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "TABLE_NOT_FOUND"
message: "Table 'nonexistent' does not exist"
statusCode: 404
nextActions: "Check table name and try again"
/api/database/migrations:
get:
summary: List Database Migrations
tags:
- Admin
security:
- bearerAuth: []
- apiKey: []
responses:
'200':
description: List successful custom migrations
content:
application/json:
schema:
type: object
required:
- migrations
properties:
migrations:
type: array
items:
$ref: '#/components/schemas/Migration'
example:
migrations:
- version: "20260416170500"
name: "create_posts_table"
statements:
- "CREATE TABLE posts (id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title TEXT NOT NULL);"
createdAt: "2026-04-16T17:05:00.000Z"
post:
summary: Create and Execute Database Migration
tags:
- Admin
security:
- bearerAuth: []
- apiKey: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- version
- name
- sql
properties:
version:
type: string
description: Numeric migration version. Accepts Drizzle-style sequential prefixes (e.g. `0001`) or a `YYYYMMDDHHmmss` timestamp. Versions are compared numerically.
pattern: '^\d{1,64}$'
maxLength: 64
name:
type: string
description: Migration name
minLength: 1
sql:
type: string
description: SQL text to parse and execute immediately
minLength: 1
example:
version: "20260416170500"
name: "create_posts_table"
sql: "CREATE TABLE posts (id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title TEXT NOT NULL);"
responses:
'201':
description: Migration executed and recorded successfully
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/Migration'
- type: object
required:
- message
properties:
message:
type: string
example:
version: "20260416170500"
name: "create_posts_table"
statements:
- "CREATE TABLE posts (id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title TEXT NOT NULL);"
createdAt: "2026-04-16T17:05:00.000Z"
message: "Migration executed successfully"
'400':
description: Invalid migration
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
examples:
invalidPayload:
value:
error: "INVALID_INPUT"
message: "sql: Migration SQL is required"
statusCode: 400
transactionStatement:
value:
error: "DATABASE_FORBIDDEN"
message: "Custom migrations cannot manage their own transactions."
statusCode: 400
'409':
description: Migration version already exists or is not newer than the latest applied migration
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "ALREADY_EXISTS"
message: "Migration version already exists."
statusCode: 409
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
apiKey:
type: apiKey
in: header
name: X-API-Key
schemas:
ForeignKeyConstraint:
type: object
description: A table-level foreign key constraint. One entry per constraint; composite keys list multiple column mappings.
required:
- referenceTable
- referenceColumns
- onDelete
- onUpdate
properties:
constraintName:
type: string
description: Constraint name. Returned when reading the schema; derived by the backend on create.
referenceTable:
type: string
minLength: 1
description: Table being referenced
referenceColumns:
type: array
minItems: 1
description: Ordered (source → reference) column pairs
items:
type: object
required:
- sourceColumn
- referenceColumn
properties:
sourceColumn:
type: string
description: Column in the current table
referenceColumn:
type: string
description: Column in the referenced table
onDelete:
type: string
enum: [CASCADE, SET NULL, SET DEFAULT, NO ACTION, RESTRICT]
onUpdate:
type: string
enum: [CASCADE, SET NULL, SET DEFAULT, NO ACTION, RESTRICT]
Migration:
type: object
required:
- version
- name
- statements
- createdAt
properties:
version:
type: string
pattern: '^\d{1,64}$'
name:
type: string
statements:
type: array
items:
type: string
createdAt:
type: string
format: date-time
ErrorResponse:
type: object
required:
- error
- message
- statusCode
properties:
error:
type: string
description: Error code for programmatic handling
message:
type: string
description: Human-readable error message
statusCode:
type: integer
description: HTTP status code
nextActions:
type: string
description: Suggested action to resolve the error