834 lines
24 KiB
YAML
834 lines
24 KiB
YAML
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"
|