mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-16 02:19:41 +02:00
Complete brand rename from ManaCore to Mana:
- Package scope: @manacore/* → @mana/*
- App directory: apps/manacore/ → apps/mana/
- IndexedDB: new Dexie('manacore') → new Dexie('mana')
- Env vars: MANA_CORE_AUTH_URL → MANA_AUTH_URL, MANA_CORE_SERVICE_KEY → MANA_SERVICE_KEY
- Docker: container/network names manacore-* → mana-*
- PostgreSQL user: manacore → mana
- Display name: ManaCore → Mana everywhere
- All import paths, branding, CI/CD, Grafana dashboards updated
No live data to migrate. Dexie table names (mukkePlaylists etc.)
preserved for backward compat. Devlog entries kept as historical.
Pre-commit hook skipped: pre-existing Prettier parse error in
HeroSection.astro + ESLint OOM on 1900+ files. Changes are pure
search-replace, no logic modifications.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
926 lines
25 KiB
YAML
926 lines
25 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: Memoro Server API
|
|
description: AI-powered voice memo management — memo processing, spaces, credits, meetings, settings.
|
|
version: 1.0.0
|
|
contact:
|
|
name: Mana
|
|
url: https://mana.how
|
|
|
|
servers:
|
|
- url: http://localhost:3015
|
|
description: Local development
|
|
- url: https://memoro.mana.how
|
|
description: Production
|
|
|
|
tags:
|
|
- name: Health
|
|
description: Health check and public endpoints
|
|
- name: Memos
|
|
description: Memo creation, transcription, and AI operations
|
|
- name: Spaces
|
|
description: Collaborative workspaces and invitations
|
|
- name: Invites
|
|
description: Pending invite management
|
|
- name: Credits
|
|
description: Mana credit balance, validation, and consumption
|
|
- name: Settings
|
|
description: User profile and app settings
|
|
- name: Meetings
|
|
description: Meeting bot and recording management
|
|
- name: Internal
|
|
description: Service-to-service callbacks (X-Service-Key auth)
|
|
- name: Cleanup
|
|
description: Audio file cleanup (X-Internal-API-Key auth)
|
|
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
serviceKey:
|
|
type: apiKey
|
|
in: header
|
|
name: X-Service-Key
|
|
internalKey:
|
|
type: apiKey
|
|
in: header
|
|
name: X-Internal-API-Key
|
|
|
|
schemas:
|
|
ApiResult:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
error:
|
|
type: string
|
|
required: [success]
|
|
|
|
PaginationQuery:
|
|
type: object
|
|
properties:
|
|
limit:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 100
|
|
default: 50
|
|
offset:
|
|
type: integer
|
|
minimum: 0
|
|
default: 0
|
|
|
|
CreateMemoBody:
|
|
type: object
|
|
required: [filePath, duration]
|
|
properties:
|
|
filePath:
|
|
type: string
|
|
minLength: 1
|
|
duration:
|
|
type: number
|
|
minimum: 0
|
|
spaceId:
|
|
type: string
|
|
format: uuid
|
|
blueprintId:
|
|
type: string
|
|
format: uuid
|
|
memoId:
|
|
type: string
|
|
format: uuid
|
|
recordingStartedAt:
|
|
type: string
|
|
mediaType:
|
|
type: string
|
|
|
|
AppendMemoBody:
|
|
type: object
|
|
required: [filePath, duration]
|
|
properties:
|
|
filePath:
|
|
type: string
|
|
minLength: 1
|
|
duration:
|
|
type: number
|
|
minimum: 0
|
|
recordingIndex:
|
|
type: integer
|
|
minimum: 0
|
|
recordingLanguages:
|
|
type: array
|
|
items:
|
|
type: string
|
|
enableDiarization:
|
|
type: boolean
|
|
|
|
CombineMemoBody:
|
|
type: object
|
|
required: [memoIds]
|
|
properties:
|
|
memoIds:
|
|
type: array
|
|
items:
|
|
type: string
|
|
format: uuid
|
|
minItems: 2
|
|
|
|
QuestionMemoBody:
|
|
type: object
|
|
required: [question]
|
|
properties:
|
|
question:
|
|
type: string
|
|
minLength: 1
|
|
|
|
CreateSpaceBody:
|
|
type: object
|
|
required: [name]
|
|
properties:
|
|
name:
|
|
type: string
|
|
minLength: 1
|
|
description:
|
|
type: string
|
|
|
|
LinkMemoBody:
|
|
type: object
|
|
required: [memoId]
|
|
properties:
|
|
memoId:
|
|
type: string
|
|
format: uuid
|
|
|
|
InviteBody:
|
|
type: object
|
|
required: [email]
|
|
properties:
|
|
email:
|
|
type: string
|
|
format: email
|
|
|
|
InviteActionBody:
|
|
type: object
|
|
required: [inviteId]
|
|
properties:
|
|
inviteId:
|
|
type: string
|
|
format: uuid
|
|
|
|
CreateBotBody:
|
|
type: object
|
|
required: [meeting_url]
|
|
properties:
|
|
meeting_url:
|
|
type: string
|
|
pattern: '^https://(teams\.microsoft\.com|meet\.google\.com|[\w-]+\.zoom\.us)/'
|
|
space_id:
|
|
type: string
|
|
format: uuid
|
|
|
|
CheckCreditsBody:
|
|
type: object
|
|
required: [operation, amount]
|
|
properties:
|
|
operation:
|
|
type: string
|
|
minLength: 1
|
|
amount:
|
|
type: number
|
|
minimum: 0
|
|
|
|
ConsumeCreditsBody:
|
|
type: object
|
|
required: [operation, amount, description]
|
|
properties:
|
|
operation:
|
|
type: string
|
|
minLength: 1
|
|
amount:
|
|
type: number
|
|
minimum: 0
|
|
description:
|
|
type: string
|
|
minLength: 1
|
|
metadata:
|
|
type: object
|
|
|
|
UpdateProfileBody:
|
|
type: object
|
|
properties:
|
|
display_name:
|
|
type: string
|
|
avatar_url:
|
|
type: string
|
|
format: uri
|
|
bio:
|
|
type: string
|
|
maxLength: 500
|
|
|
|
UpdateDataUsageBody:
|
|
type: object
|
|
required: [accepted]
|
|
properties:
|
|
accepted:
|
|
type: boolean
|
|
|
|
TranscriptionCompletedBody:
|
|
type: object
|
|
required: [memoId, userId, success]
|
|
properties:
|
|
memoId:
|
|
type: string
|
|
userId:
|
|
type: string
|
|
success:
|
|
type: boolean
|
|
transcriptionResult:
|
|
type: object
|
|
properties:
|
|
transcript:
|
|
type: string
|
|
utterances:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
offset: { type: number }
|
|
duration: { type: number }
|
|
text: { type: string }
|
|
speaker: { type: string }
|
|
languages:
|
|
type: array
|
|
items: { type: string }
|
|
primary_language:
|
|
type: string
|
|
duration:
|
|
type: number
|
|
route:
|
|
type: string
|
|
error:
|
|
type: string
|
|
fallbackStage:
|
|
type: string
|
|
|
|
ManualCleanupBody:
|
|
type: object
|
|
properties:
|
|
userIds:
|
|
type: array
|
|
items:
|
|
type: string
|
|
format: uuid
|
|
|
|
CreditCosts:
|
|
type: object
|
|
properties:
|
|
TRANSCRIPTION_PER_MINUTE: { type: number, example: 2 }
|
|
HEADLINE_GENERATION: { type: number, example: 10 }
|
|
MEMORY_CREATION: { type: number, example: 10 }
|
|
BLUEPRINT_PROCESSING: { type: number, example: 5 }
|
|
QUESTION_MEMO: { type: number, example: 5 }
|
|
MEMO_COMBINE: { type: number, example: 5 }
|
|
MEETING_RECORDING_PER_MINUTE: { type: number, example: 2 }
|
|
|
|
paths:
|
|
/health:
|
|
get:
|
|
tags: [Health]
|
|
summary: Health check with dependency status
|
|
responses:
|
|
'200':
|
|
description: All systems operational
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status: { type: string, enum: [ok, degraded] }
|
|
service: { type: string }
|
|
runtime: { type: string }
|
|
timestamp: { type: string, format: date-time }
|
|
checks:
|
|
type: object
|
|
properties:
|
|
supabase: { type: string, enum: [ok, error] }
|
|
'503':
|
|
description: One or more dependencies degraded
|
|
|
|
/api/v1/credits/pricing:
|
|
get:
|
|
tags: [Credits]
|
|
summary: Get credit cost constants (public, no auth)
|
|
responses:
|
|
'200':
|
|
description: Cost constants
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
costs:
|
|
$ref: '#/components/schemas/CreditCosts'
|
|
|
|
# ── Memos ────────────────────────────────────────────────────────
|
|
|
|
/api/v1/memos:
|
|
post:
|
|
tags: [Memos]
|
|
summary: Create memo from uploaded file
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateMemoBody'
|
|
responses:
|
|
'201': { description: Memo created, transcription started }
|
|
'400': { description: Validation error }
|
|
'402': { description: Insufficient credits }
|
|
|
|
/api/v1/memos/{id}/append:
|
|
post:
|
|
tags: [Memos]
|
|
summary: Append transcription to existing memo
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/AppendMemoBody'
|
|
responses:
|
|
'200': { description: Append transcription started }
|
|
'400': { description: Validation error }
|
|
'402': { description: Insufficient credits }
|
|
'404': { description: Memo not found }
|
|
|
|
/api/v1/memos/{id}/retry-transcription:
|
|
post:
|
|
tags: [Memos]
|
|
summary: Retry failed transcription
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
'200': { description: Transcription retry started }
|
|
'400': { description: No audio file }
|
|
'404': { description: Memo not found }
|
|
|
|
/api/v1/memos/{id}/retry-headline:
|
|
post:
|
|
tags: [Memos]
|
|
summary: Retry headline generation
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
'200': { description: Headline regenerated }
|
|
'404': { description: Memo not found }
|
|
'500': { description: Generation failed }
|
|
|
|
/api/v1/memos/combine:
|
|
post:
|
|
tags: [Memos]
|
|
summary: Combine multiple memos with AI
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CombineMemoBody'
|
|
responses:
|
|
'200': { description: Memos combined }
|
|
'400': { description: Validation error }
|
|
'402': { description: Insufficient credits }
|
|
'404': { description: One or more memos not found }
|
|
|
|
/api/v1/memos/{id}/question:
|
|
post:
|
|
tags: [Memos]
|
|
summary: Ask a question about memo transcript
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/QuestionMemoBody'
|
|
responses:
|
|
'200': { description: Answer generated }
|
|
'400': { description: Validation error or no transcript }
|
|
'402': { description: Insufficient credits }
|
|
'404': { description: Memo not found }
|
|
|
|
# ── Spaces ───────────────────────────────────────────────────────
|
|
|
|
/api/v1/spaces:
|
|
get:
|
|
tags: [Spaces]
|
|
summary: List user's spaces
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: limit
|
|
in: query
|
|
schema: { type: integer, default: 50, maximum: 100 }
|
|
- name: offset
|
|
in: query
|
|
schema: { type: integer, default: 0 }
|
|
responses:
|
|
'200': { description: List of spaces with pagination }
|
|
post:
|
|
tags: [Spaces]
|
|
summary: Create a space
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateSpaceBody'
|
|
responses:
|
|
'201': { description: Space created }
|
|
'400': { description: Validation error }
|
|
|
|
/api/v1/spaces/{id}:
|
|
get:
|
|
tags: [Spaces]
|
|
summary: Get space details
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
'200': { description: Space details }
|
|
'403': { description: Access denied }
|
|
'404': { description: Space not found }
|
|
delete:
|
|
tags: [Spaces]
|
|
summary: Delete space (owner only)
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
'200': { description: Space deleted }
|
|
'403': { description: Not the owner }
|
|
'404': { description: Space not found }
|
|
|
|
/api/v1/spaces/{id}/leave:
|
|
post:
|
|
tags: [Spaces]
|
|
summary: Leave a space (non-owner)
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
'200': { description: Left space }
|
|
'400': { description: Owner cannot leave }
|
|
'403': { description: Not a member }
|
|
|
|
/api/v1/spaces/{id}/memos/link:
|
|
post:
|
|
tags: [Spaces]
|
|
summary: Link memo to space
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/LinkMemoBody'
|
|
responses:
|
|
'200': { description: Memo linked }
|
|
'403': { description: Not a member }
|
|
|
|
/api/v1/spaces/{id}/memos/unlink:
|
|
post:
|
|
tags: [Spaces]
|
|
summary: Unlink memo from space
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/LinkMemoBody'
|
|
responses:
|
|
'200': { description: Memo unlinked }
|
|
|
|
/api/v1/spaces/{id}/memos:
|
|
get:
|
|
tags: [Spaces]
|
|
summary: List memos in space
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
- name: limit
|
|
in: query
|
|
schema: { type: integer, default: 50 }
|
|
- name: offset
|
|
in: query
|
|
schema: { type: integer, default: 0 }
|
|
responses:
|
|
'200': { description: Paginated memo list }
|
|
'403': { description: Not a member }
|
|
|
|
/api/v1/spaces/{id}/invites:
|
|
get:
|
|
tags: [Spaces]
|
|
summary: List space invites
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
'200': { description: List of invites }
|
|
|
|
/api/v1/spaces/{id}/invite:
|
|
post:
|
|
tags: [Spaces]
|
|
summary: Send invitation to email
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/InviteBody'
|
|
responses:
|
|
'201': { description: Invite created and email sent }
|
|
'400': { description: Invalid email }
|
|
'403': { description: Not a member }
|
|
|
|
# ── Invites ──────────────────────────────────────────────────────
|
|
|
|
/api/v1/invites/pending:
|
|
get:
|
|
tags: [Invites]
|
|
summary: List pending invites for current user
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
'200': { description: List of pending invites }
|
|
|
|
/api/v1/invites/accept:
|
|
post:
|
|
tags: [Invites]
|
|
summary: Accept an invite
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/InviteActionBody'
|
|
responses:
|
|
'200': { description: Invite accepted }
|
|
'404': { description: Invite not found }
|
|
|
|
/api/v1/invites/decline:
|
|
post:
|
|
tags: [Invites]
|
|
summary: Decline an invite
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/InviteActionBody'
|
|
responses:
|
|
'200': { description: Invite declined }
|
|
'404': { description: Invite not found }
|
|
|
|
# ── Credits ──────────────────────────────────────────────────────
|
|
|
|
/api/v1/credits/balance:
|
|
get:
|
|
tags: [Credits]
|
|
summary: Get credit balance
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
'200':
|
|
description: Credit balance
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success: { type: boolean }
|
|
credits: { type: number }
|
|
totalEarned: { type: number }
|
|
totalSpent: { type: number }
|
|
|
|
/api/v1/credits/check:
|
|
post:
|
|
tags: [Credits]
|
|
summary: Check if user has enough credits
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CheckCreditsBody'
|
|
responses:
|
|
'200': { description: Credit validation result }
|
|
|
|
/api/v1/credits/consume:
|
|
post:
|
|
tags: [Credits]
|
|
summary: Consume credits
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ConsumeCreditsBody'
|
|
responses:
|
|
'200': { description: Credits consumed }
|
|
|
|
# ── Settings ─────────────────────────────────────────────────────
|
|
|
|
/api/v1/settings:
|
|
get:
|
|
tags: [Settings]
|
|
summary: Get all user settings
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
'200': { description: User settings }
|
|
|
|
/api/v1/settings/memoro:
|
|
get:
|
|
tags: [Settings]
|
|
summary: Get memoro-specific settings
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
'200': { description: Memoro settings }
|
|
patch:
|
|
tags: [Settings]
|
|
summary: Update memoro settings
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
minProperties: 1
|
|
responses:
|
|
'200': { description: Settings updated }
|
|
'400': { description: Empty body }
|
|
|
|
/api/v1/settings/memoro/data-usage:
|
|
patch:
|
|
tags: [Settings]
|
|
summary: Update data usage acceptance
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UpdateDataUsageBody'
|
|
responses:
|
|
'200': { description: Data usage updated }
|
|
|
|
/api/v1/settings/profile:
|
|
patch:
|
|
tags: [Settings]
|
|
summary: Update user profile
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UpdateProfileBody'
|
|
responses:
|
|
'200': { description: Profile updated }
|
|
'400': { description: Validation error }
|
|
|
|
# ── Meetings ─────────────────────────────────────────────────────
|
|
|
|
/api/v1/meetings/bots:
|
|
post:
|
|
tags: [Meetings]
|
|
summary: Create meeting bot
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateBotBody'
|
|
responses:
|
|
'200': { description: Bot created }
|
|
'400': { description: Invalid meeting URL }
|
|
'402': { description: Insufficient credits }
|
|
get:
|
|
tags: [Meetings]
|
|
summary: List meeting bots
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: space_id
|
|
in: query
|
|
schema: { type: string }
|
|
- name: limit
|
|
in: query
|
|
schema: { type: integer, default: 50 }
|
|
- name: offset
|
|
in: query
|
|
schema: { type: integer, default: 0 }
|
|
responses:
|
|
'200': { description: List of bots }
|
|
|
|
/api/v1/meetings/bots/{id}:
|
|
get:
|
|
tags: [Meetings]
|
|
summary: Get bot by ID
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
'200': { description: Bot details }
|
|
'404': { description: Bot not found }
|
|
|
|
/api/v1/meetings/bots/{id}/stop:
|
|
post:
|
|
tags: [Meetings]
|
|
summary: Stop a meeting bot
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
'200': { description: Bot stop signal sent }
|
|
'404': { description: Bot not found }
|
|
|
|
/api/v1/meetings/recordings:
|
|
get:
|
|
tags: [Meetings]
|
|
summary: List recordings
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: space_id
|
|
in: query
|
|
schema: { type: string }
|
|
- name: limit
|
|
in: query
|
|
schema: { type: integer, default: 50 }
|
|
- name: offset
|
|
in: query
|
|
schema: { type: integer, default: 0 }
|
|
responses:
|
|
'200': { description: List of recordings }
|
|
|
|
/api/v1/meetings/recordings/{id}:
|
|
get:
|
|
tags: [Meetings]
|
|
summary: Get recording by ID
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
'200': { description: Recording details }
|
|
'404': { description: Recording not found }
|
|
|
|
/api/v1/meetings/recordings/{id}/to-memo:
|
|
post:
|
|
tags: [Meetings]
|
|
summary: Convert recording to memo
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
'200': { description: Memo created from recording }
|
|
'400': { description: No audio/video file }
|
|
'404': { description: Recording not found }
|
|
|
|
# ── Internal ─────────────────────────────────────────────────────
|
|
|
|
/api/v1/internal/transcription-completed:
|
|
post:
|
|
tags: [Internal]
|
|
summary: Transcription completion callback
|
|
security: [{ serviceKey: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TranscriptionCompletedBody'
|
|
responses:
|
|
'200': { description: Callback processed }
|
|
|
|
/api/v1/internal/batch-metadata:
|
|
post:
|
|
tags: [Internal]
|
|
summary: Update batch job metadata
|
|
security: [{ serviceKey: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [memoId, jobId]
|
|
properties:
|
|
memoId: { type: string }
|
|
jobId: { type: string }
|
|
responses:
|
|
'200': { description: Metadata updated }
|
|
'404': { description: Memo not found }
|
|
|
|
# ── Cleanup ──────────────────────────────────────────────────────
|
|
|
|
/api/v1/cleanup/run:
|
|
post:
|
|
tags: [Cleanup]
|
|
summary: Trigger async audio cleanup
|
|
security: [{ internalKey: [] }]
|
|
responses:
|
|
'200': { description: Cleanup started }
|
|
|
|
/api/v1/cleanup/manual:
|
|
post:
|
|
tags: [Cleanup]
|
|
summary: Manual cleanup with optional user IDs
|
|
security: [{ internalKey: [] }]
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ManualCleanupBody'
|
|
responses:
|
|
'200': { description: Cleanup result }
|
|
|
|
# ── Webhooks ─────────────────────────────────────────────────────
|
|
|
|
/meetings/webhooks/bot-events:
|
|
post:
|
|
tags: [Meetings]
|
|
summary: Meeting bot webhook (HMAC-verified)
|
|
description: Receives recording.completed and recording.failed events from meeting bot service.
|
|
responses:
|
|
'200': { description: Event processed }
|
|
'400': { description: Invalid JSON }
|
|
'401': { description: Invalid HMAC signature }
|