diff --git a/api-reference/accounts/add-artist.mdx b/api-reference/accounts/add-artist.mdx index 33f2fe3..7daff8f 100644 --- a/api-reference/accounts/add-artist.mdx +++ b/api-reference/accounts/add-artist.mdx @@ -1,4 +1,4 @@ --- title: 'Add Artist to Account' -openapi: 'POST /api/accounts/artists' +openapi: "/api-reference/openapi/accounts.json POST /api/accounts/artists" --- diff --git a/api-reference/accounts/create.mdx b/api-reference/accounts/create.mdx index 67d37c6..038fcb5 100644 --- a/api-reference/accounts/create.mdx +++ b/api-reference/accounts/create.mdx @@ -1,4 +1,4 @@ --- title: 'Create Account' -openapi: 'POST /api/accounts' +openapi: "/api-reference/openapi/accounts.json POST /api/accounts" --- diff --git a/api-reference/accounts/get.mdx b/api-reference/accounts/get.mdx index eb63b7b..c640217 100644 --- a/api-reference/accounts/get.mdx +++ b/api-reference/accounts/get.mdx @@ -1,4 +1,4 @@ --- title: 'Get Account' -openapi: 'GET /api/accounts/{id}' +openapi: "/api-reference/openapi/accounts.json GET /api/accounts/{id}" --- diff --git a/api-reference/accounts/id.mdx b/api-reference/accounts/id.mdx index 33a52d9..3ced709 100644 --- a/api-reference/accounts/id.mdx +++ b/api-reference/accounts/id.mdx @@ -1,4 +1,4 @@ --- title: 'Get Account ID' -openapi: 'GET /api/accounts/id' +openapi: "/api-reference/openapi/accounts.json GET /api/accounts/id" --- diff --git a/api-reference/accounts/update.mdx b/api-reference/accounts/update.mdx index dc622e4..494ee95 100644 --- a/api-reference/accounts/update.mdx +++ b/api-reference/accounts/update.mdx @@ -1,4 +1,4 @@ --- title: 'Update Account' -openapi: 'PATCH /api/accounts' +openapi: "/api-reference/openapi/accounts.json PATCH /api/accounts" --- diff --git a/api-reference/admins/check.mdx b/api-reference/admins/check.mdx index 5d874fd..c7abc26 100644 --- a/api-reference/admins/check.mdx +++ b/api-reference/admins/check.mdx @@ -1,4 +1,4 @@ --- title: 'Check Admin Status' -openapi: 'GET /api/admins' +openapi: "/api-reference/openapi/accounts.json GET /api/admins" --- diff --git a/api-reference/admins/coding-agent-slack-tags.mdx b/api-reference/admins/coding-agent-slack-tags.mdx index c10eeb5..9178c97 100644 --- a/api-reference/admins/coding-agent-slack-tags.mdx +++ b/api-reference/admins/coding-agent-slack-tags.mdx @@ -1,4 +1,4 @@ --- title: 'List Coding Agent Slack Tags (Admin)' -openapi: 'GET /api/admins/coding/slack' +openapi: "/api-reference/openapi/accounts.json GET /api/admins/coding/slack" --- diff --git a/api-reference/admins/coding-pr.mdx b/api-reference/admins/coding-pr.mdx index ce9ae16..1280def 100644 --- a/api-reference/admins/coding-pr.mdx +++ b/api-reference/admins/coding-pr.mdx @@ -1,4 +1,4 @@ --- title: 'Get Coding Agent PR Merged Status (Admin)' -openapi: 'GET /api/admins/coding/pr' +openapi: "/api-reference/openapi/accounts.json GET /api/admins/coding/pr" --- diff --git a/api-reference/admins/content-slack-tags.mdx b/api-reference/admins/content-slack-tags.mdx index 00dcafe..3c7ce0c 100644 --- a/api-reference/admins/content-slack-tags.mdx +++ b/api-reference/admins/content-slack-tags.mdx @@ -1,4 +1,4 @@ --- title: 'List Content Agent Slack Tags (Admin)' -openapi: 'GET /api/admins/content/slack' +openapi: "/api-reference/openapi/accounts.json GET /api/admins/content/slack" --- diff --git a/api-reference/admins/emails.mdx b/api-reference/admins/emails.mdx index 5e92c9f..861d4c5 100644 --- a/api-reference/admins/emails.mdx +++ b/api-reference/admins/emails.mdx @@ -1,4 +1,4 @@ --- title: 'List Account Emails (Admin)' -openapi: 'GET /api/admins/emails' +openapi: "/api-reference/openapi/accounts.json GET /api/admins/emails" --- diff --git a/api-reference/admins/privy.mdx b/api-reference/admins/privy.mdx index d91e468..9e77a9a 100644 --- a/api-reference/admins/privy.mdx +++ b/api-reference/admins/privy.mdx @@ -1,4 +1,4 @@ --- title: 'List Privy Logins (Admin)' -openapi: 'GET /api/admins/privy' +openapi: "/api-reference/openapi/accounts.json GET /api/admins/privy" --- diff --git a/api-reference/admins/sandboxes-orgs.mdx b/api-reference/admins/sandboxes-orgs.mdx index 575b81f..b567063 100644 --- a/api-reference/admins/sandboxes-orgs.mdx +++ b/api-reference/admins/sandboxes-orgs.mdx @@ -1,4 +1,4 @@ --- title: 'List Org Repo Stats (Admin)' -openapi: 'GET /api/admins/sandboxes/orgs' +openapi: "/api-reference/openapi/accounts.json GET /api/admins/sandboxes/orgs" --- diff --git a/api-reference/admins/sandboxes.mdx b/api-reference/admins/sandboxes.mdx index 473fce7..a9fb2ef 100644 --- a/api-reference/admins/sandboxes.mdx +++ b/api-reference/admins/sandboxes.mdx @@ -1,4 +1,4 @@ --- title: 'List Account Sandboxes (Admin)' -openapi: 'GET /api/admins/sandboxes' +openapi: "/api-reference/openapi/accounts.json GET /api/admins/sandboxes" --- diff --git a/api-reference/apify/scraper.mdx b/api-reference/apify/scraper.mdx index 9c47bde..8c47089 100644 --- a/api-reference/apify/scraper.mdx +++ b/api-reference/apify/scraper.mdx @@ -1,4 +1,4 @@ --- title: 'Scraper Results' -openapi: 'GET /api/apify/scraper' +openapi: "/api-reference/openapi/social.json GET /api/apify/scraper" --- diff --git a/api-reference/artist/profile.mdx b/api-reference/artist/profile.mdx index 9b4d78e..a33d0df 100644 --- a/api-reference/artist/profile.mdx +++ b/api-reference/artist/profile.mdx @@ -1,4 +1,4 @@ --- title: Get Artist Profile -openapi: GET /api/artist-profile +openapi: "/api-reference/openapi/releases.json GET /api/artist-profile" --- diff --git a/api-reference/artist/segments.mdx b/api-reference/artist/segments.mdx index d584010..cad734b 100644 --- a/api-reference/artist/segments.mdx +++ b/api-reference/artist/segments.mdx @@ -1,4 +1,4 @@ --- title: Get Artist Segments -openapi: GET /api/artist/segments +openapi: "/api-reference/openapi/releases.json GET /api/artist/segments" --- diff --git a/api-reference/artist/socials.mdx b/api-reference/artist/socials.mdx index b3062f6..f3ebf26 100644 --- a/api-reference/artist/socials.mdx +++ b/api-reference/artist/socials.mdx @@ -1,4 +1,4 @@ --- title: Get Artist Socials -openapi: GET /api/artist/socials +openapi: "/api-reference/openapi/releases.json GET /api/artist/socials" --- diff --git a/api-reference/artists/create.mdx b/api-reference/artists/create.mdx index df5c2c7..0d7d2fa 100644 --- a/api-reference/artists/create.mdx +++ b/api-reference/artists/create.mdx @@ -1,4 +1,4 @@ --- title: 'Create Artist' -openapi: 'POST /api/artists' +openapi: "/api-reference/openapi/releases.json POST /api/artists" --- diff --git a/api-reference/artists/list.mdx b/api-reference/artists/list.mdx index 0d4fff2..2fd5da0 100644 --- a/api-reference/artists/list.mdx +++ b/api-reference/artists/list.mdx @@ -1,4 +1,4 @@ --- title: 'Get Artists' -openapi: 'GET /api/artists' +openapi: "/api-reference/openapi/releases.json GET /api/artists" --- diff --git a/api-reference/chat/artist.mdx b/api-reference/chat/artist.mdx index dbab957..5f91410 100644 --- a/api-reference/chat/artist.mdx +++ b/api-reference/chat/artist.mdx @@ -1,4 +1,4 @@ --- title: "Get Chat Artist" -openapi: GET /api/chats/{id}/artist +openapi: "/api-reference/openapi/research.json GET /api/chats/{id}/artist" --- diff --git a/api-reference/chat/chats.mdx b/api-reference/chat/chats.mdx index a25f088..37d3068 100644 --- a/api-reference/chat/chats.mdx +++ b/api-reference/chat/chats.mdx @@ -1,4 +1,4 @@ --- title: Get Chats -openapi: GET /api/chats +openapi: "/api-reference/openapi/research.json GET /api/chats" --- diff --git a/api-reference/chat/compact.mdx b/api-reference/chat/compact.mdx index 96148e4..d873775 100644 --- a/api-reference/chat/compact.mdx +++ b/api-reference/chat/compact.mdx @@ -1,4 +1,4 @@ --- title: 'Compact Chats' -openapi: 'POST /api/chats/compact' +openapi: "/api-reference/openapi/research.json POST /api/chats/compact" --- diff --git a/api-reference/chat/messages-copy.mdx b/api-reference/chat/messages-copy.mdx index a6b34c7..aab9a18 100644 --- a/api-reference/chat/messages-copy.mdx +++ b/api-reference/chat/messages-copy.mdx @@ -1,4 +1,4 @@ --- title: "Copy Chat Messages" -openapi: POST /api/chats/{id}/messages/copy +openapi: "/api-reference/openapi/research.json POST /api/chats/{id}/messages/copy" --- diff --git a/api-reference/chat/messages-trailing-delete.mdx b/api-reference/chat/messages-trailing-delete.mdx index a756de8..8df9f2f 100644 --- a/api-reference/chat/messages-trailing-delete.mdx +++ b/api-reference/chat/messages-trailing-delete.mdx @@ -1,4 +1,4 @@ --- title: "Delete Trailing Chat Messages" -openapi: "DELETE /api/chats/{id}/messages/trailing" +openapi: "/api-reference/openapi/research.json DELETE /api/chats/{id}/messages/trailing" --- diff --git a/api-reference/chat/messages.mdx b/api-reference/chat/messages.mdx index 34db510..c79e17c 100644 --- a/api-reference/chat/messages.mdx +++ b/api-reference/chat/messages.mdx @@ -1,4 +1,4 @@ --- title: Get Chat Messages -openapi: GET /api/chats/{id}/messages +openapi: "/api-reference/openapi/research.json GET /api/chats/{id}/messages" --- diff --git a/api-reference/chat/segment.mdx b/api-reference/chat/segment.mdx index 34becf2..d957752 100644 --- a/api-reference/chat/segment.mdx +++ b/api-reference/chat/segment.mdx @@ -1,4 +1,4 @@ --- title: "Get Chat Segment" -openapi: GET /api/chats/{id}/segment +openapi: "/api-reference/openapi/research.json GET /api/chats/{id}/segment" --- diff --git a/api-reference/comments/get.mdx b/api-reference/comments/get.mdx index 6302f31..6cfa7a8 100644 --- a/api-reference/comments/get.mdx +++ b/api-reference/comments/get.mdx @@ -1,4 +1,4 @@ --- title: Get Comments -openapi: GET /api/comments +openapi: "/api-reference/openapi/social.json GET /api/comments" --- diff --git a/api-reference/connectors/authorize.mdx b/api-reference/connectors/authorize.mdx index 3114fc2..c9a9895 100644 --- a/api-reference/connectors/authorize.mdx +++ b/api-reference/connectors/authorize.mdx @@ -1,4 +1,4 @@ --- title: 'Authorize Connector' -openapi: 'POST /api/connectors' +openapi: "/api-reference/openapi/social.json POST /api/connectors" --- diff --git a/api-reference/connectors/disconnect.mdx b/api-reference/connectors/disconnect.mdx index ff03791..aced467 100644 --- a/api-reference/connectors/disconnect.mdx +++ b/api-reference/connectors/disconnect.mdx @@ -1,4 +1,4 @@ --- title: 'Disconnect Connector' -openapi: 'DELETE /api/connectors' +openapi: "/api-reference/openapi/social.json DELETE /api/connectors" --- diff --git a/api-reference/connectors/list.mdx b/api-reference/connectors/list.mdx index e8ccd7d..26431d7 100644 --- a/api-reference/connectors/list.mdx +++ b/api-reference/connectors/list.mdx @@ -1,4 +1,4 @@ --- title: 'List Connectors' -openapi: 'GET /api/connectors' +openapi: "/api-reference/openapi/social.json GET /api/connectors" --- diff --git a/api-reference/content-agent/callback.mdx b/api-reference/content-agent/callback.mdx index 1be4bdf..a766b7c 100644 --- a/api-reference/content-agent/callback.mdx +++ b/api-reference/content-agent/callback.mdx @@ -1,4 +1,4 @@ --- title: 'Task Callback' -openapi: 'POST /api/content-agent/callback' +openapi: "/api-reference/openapi/content.json POST /api/content-agent/callback" --- diff --git a/api-reference/content-agent/webhook.mdx b/api-reference/content-agent/webhook.mdx index 723d8bc..3e9fd10 100644 --- a/api-reference/content-agent/webhook.mdx +++ b/api-reference/content-agent/webhook.mdx @@ -1,4 +1,4 @@ --- title: 'Slack Webhook' -openapi: 'POST /api/content-agent/{platform}' +openapi: "/api-reference/openapi/content.json POST /api/content-agent/{platform}" --- diff --git a/api-reference/content/analyze-video.mdx b/api-reference/content/analyze-video.mdx index 4c0756e..15c7cf4 100644 --- a/api-reference/content/analyze-video.mdx +++ b/api-reference/content/analyze-video.mdx @@ -1,4 +1,4 @@ --- title: 'Analyze Video' -openapi: 'POST /api/content/analyze' +openapi: "/api-reference/openapi/content.json POST /api/content/analyze" --- diff --git a/api-reference/content/create.mdx b/api-reference/content/create.mdx index d9f0af3..b3bf5d7 100644 --- a/api-reference/content/create.mdx +++ b/api-reference/content/create.mdx @@ -1,4 +1,4 @@ --- title: 'Create Content' -openapi: 'POST /api/content/create' +openapi: "/api-reference/openapi/content.json POST /api/content/create" --- diff --git a/api-reference/content/edit.mdx b/api-reference/content/edit.mdx index e70820d..4635008 100644 --- a/api-reference/content/edit.mdx +++ b/api-reference/content/edit.mdx @@ -1,4 +1,4 @@ --- title: 'Edit Content' -openapi: 'PATCH /api/content' +openapi: "/api-reference/openapi/content.json PATCH /api/content" --- diff --git a/api-reference/content/estimate.mdx b/api-reference/content/estimate.mdx index 244dd93..9c1b919 100644 --- a/api-reference/content/estimate.mdx +++ b/api-reference/content/estimate.mdx @@ -1,4 +1,4 @@ --- title: 'Estimate Cost' -openapi: 'GET /api/content/estimate' +openapi: "/api-reference/openapi/content.json GET /api/content/estimate" --- diff --git a/api-reference/content/generate-caption.mdx b/api-reference/content/generate-caption.mdx index 093f209..ac93973 100644 --- a/api-reference/content/generate-caption.mdx +++ b/api-reference/content/generate-caption.mdx @@ -1,4 +1,4 @@ --- title: 'Generate Caption' -openapi: 'POST /api/content/caption' +openapi: "/api-reference/openapi/content.json POST /api/content/caption" --- diff --git a/api-reference/content/generate-image.mdx b/api-reference/content/generate-image.mdx index ba8238d..e3a1453 100644 --- a/api-reference/content/generate-image.mdx +++ b/api-reference/content/generate-image.mdx @@ -1,4 +1,4 @@ --- title: 'Generate Image' -openapi: 'POST /api/content/image' +openapi: "/api-reference/openapi/content.json POST /api/content/image" --- diff --git a/api-reference/content/generate-video.mdx b/api-reference/content/generate-video.mdx index 152a415..31f0a14 100644 --- a/api-reference/content/generate-video.mdx +++ b/api-reference/content/generate-video.mdx @@ -1,4 +1,4 @@ --- title: 'Generate Video' -openapi: 'POST /api/content/video' +openapi: "/api-reference/openapi/content.json POST /api/content/video" --- diff --git a/api-reference/content/template-detail.mdx b/api-reference/content/template-detail.mdx index a7daf1a..d5e65a5 100644 --- a/api-reference/content/template-detail.mdx +++ b/api-reference/content/template-detail.mdx @@ -1,4 +1,4 @@ --- title: 'Get Template Detail' -openapi: 'GET /api/content/templates/{id}' +openapi: "/api-reference/openapi/content.json GET /api/content/templates/{id}" --- diff --git a/api-reference/content/templates.mdx b/api-reference/content/templates.mdx index ff8a568..61be540 100644 --- a/api-reference/content/templates.mdx +++ b/api-reference/content/templates.mdx @@ -1,4 +1,4 @@ --- title: 'List Templates' -openapi: 'GET /api/content/templates' +openapi: "/api-reference/openapi/content.json GET /api/content/templates" --- diff --git a/api-reference/content/transcribe-audio.mdx b/api-reference/content/transcribe-audio.mdx index fb85b41..e039859 100644 --- a/api-reference/content/transcribe-audio.mdx +++ b/api-reference/content/transcribe-audio.mdx @@ -1,4 +1,4 @@ --- title: 'Transcribe Audio' -openapi: 'POST /api/content/transcribe' +openapi: "/api-reference/openapi/content.json POST /api/content/transcribe" --- diff --git a/api-reference/content/upscale.mdx b/api-reference/content/upscale.mdx index 61b6c70..6c16ea1 100644 --- a/api-reference/content/upscale.mdx +++ b/api-reference/content/upscale.mdx @@ -1,4 +1,4 @@ --- title: 'Upscale Content' -openapi: 'POST /api/content/upscale' +openapi: "/api-reference/openapi/content.json POST /api/content/upscale" --- diff --git a/api-reference/content/validate.mdx b/api-reference/content/validate.mdx index d716603..3b42eb4 100644 --- a/api-reference/content/validate.mdx +++ b/api-reference/content/validate.mdx @@ -1,4 +1,4 @@ --- title: 'Validate Artist' -openapi: 'GET /api/content/validate' +openapi: "/api-reference/openapi/content.json GET /api/content/validate" --- diff --git a/api-reference/fans/get.mdx b/api-reference/fans/get.mdx index 3722cc8..a4803e1 100644 --- a/api-reference/fans/get.mdx +++ b/api-reference/fans/get.mdx @@ -1,4 +1,4 @@ --- title: Get Artist Fans -openapi: GET /api/fans +openapi: "/api-reference/openapi/releases.json GET /api/fans" --- diff --git a/api-reference/image/generation.mdx b/api-reference/image/generation.mdx index 74a53ac..9895a33 100644 --- a/api-reference/image/generation.mdx +++ b/api-reference/image/generation.mdx @@ -1,4 +1,4 @@ --- title: 'Generate Image' -openapi: 'GET /api/image/generate' +openapi: "/api-reference/openapi/content.json GET /api/image/generate" --- diff --git a/api-reference/instagram/comments.mdx b/api-reference/instagram/comments.mdx index d7baf70..d063124 100644 --- a/api-reference/instagram/comments.mdx +++ b/api-reference/instagram/comments.mdx @@ -1,4 +1,4 @@ --- title: 'Comments' -openapi: 'GET /api/instagram/comments' +openapi: "/api-reference/openapi/social.json GET /api/instagram/comments" --- diff --git a/api-reference/instagram/profiles.mdx b/api-reference/instagram/profiles.mdx index 80a4094..8e20238 100644 --- a/api-reference/instagram/profiles.mdx +++ b/api-reference/instagram/profiles.mdx @@ -1,4 +1,4 @@ --- title: 'Profiles' -openapi: 'GET /api/instagram/profiles' +openapi: "/api-reference/openapi/social.json GET /api/instagram/profiles" --- diff --git a/api-reference/notifications/create.mdx b/api-reference/notifications/create.mdx index 664176c..1d1d161 100644 --- a/api-reference/notifications/create.mdx +++ b/api-reference/notifications/create.mdx @@ -1,4 +1,4 @@ --- title: 'Send Notification' -openapi: 'POST /api/notifications' +openapi: "/api-reference/openapi/accounts.json POST /api/notifications" --- diff --git a/api-reference/openapi.json b/api-reference/openapi.json deleted file mode 100644 index 2e67159..0000000 --- a/api-reference/openapi.json +++ /dev/null @@ -1,16408 +0,0 @@ -{ - "openapi": "3.1.0", - "info": { - "title": "Recoup API", - "description": "API documentation for the Recoup platform - an AI agent platform for the music industry", - "license": { - "name": "MIT" - }, - "version": "1.0.0" - }, - "servers": [ - { - "url": "https://recoup-api.vercel.app" - } - ], - "security": [ - { - "apiKeyAuth": [] - } - ], - "paths": { - "/api/tasks": { - "get": { - "description": "Retrieve scheduled tasks. The response includes recent_runs (last 5 runs) and upcoming (next scheduled run times) sourced directly from the Trigger.dev API. Supports filtering by id, account_id, or artist_account_id.", - "parameters": [ - { - "name": "id", - "in": "query", - "description": "Filter by task ID (UUID). Returns a single task matching the provided ID.", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "account_id", - "in": "query", - "description": "Filter tasks to only include those for the specified account.", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "artist_account_id", - "in": "query", - "description": "Filter tasks to only include those for the specified artist account.", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Tasks retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TasksResponse" - } - } - } - }, - "400": { - "description": "Bad request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - }, - "post": { - "description": "Create a new scheduled task. All fields are required. The response shape matches the GET endpoint (an array containing the created task).", - "requestBody": { - "description": "Task to create", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateTaskRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Task created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TasksResponse" - } - } - } - }, - "400": { - "description": "Bad request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - }, - "patch": { - "description": "Update an existing scheduled task. Only the id field is required; any additional fields you include will be updated on the task. The response shape matches the GET endpoint (an array containing the updated task).", - "requestBody": { - "description": "Task fields to update", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateTaskRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Task updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TasksResponse" - } - } - } - }, - "400": { - "description": "Bad request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - }, - "delete": { - "description": "Delete an existing scheduled task by its ID. Returns the status of the delete operation.", - "requestBody": { - "description": "Task to delete", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteTaskRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Task deleted successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteTaskResponse" - } - } - } - }, - "400": { - "description": "Bad request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - } - }, - "/api/tasks/runs": { - "get": { - "description": "Returns an array of task runs. When runId is provided, the array contains that single run. When omitted, returns recent runs for the authenticated account. Use account_id to query runs for a specific account within your organizations.", - "parameters": [ - { - "name": "runId", - "in": "query", - "description": "The unique identifier of a specific task run to retrieve. If omitted, returns a list of recent runs for the authenticated account.", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Maximum number of runs to return when listing (ignored when runId is provided). Default 20, max 100.", - "required": false, - "schema": { - "type": "integer", - "default": 20, - "minimum": 1, - "maximum": 100 - } - }, - { - "name": "account_id", - "in": "query", - "description": "Filter runs by account ID. When provided, returns runs tagged with account:. Only applicable when the authenticated account has access to multiple accounts via organization membership.", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Task runs retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TaskRunListResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "403": { - "description": "Forbidden - account_id is not accessible with the provided credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "404": { - "description": "Task run not found (only when runId is provided)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - } - }, - "/api/accounts/{id}": { - "get": { - "description": "Retrieve detailed account information by ID. Returns the account with associated profile info, emails, and wallet addresses.", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "The unique identifier (UUID) of the account", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Account retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetAccountResponse" - } - } - } - }, - "404": { - "description": "Account not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - } - } - } - }, - "/api/accounts/id": { - "get": { - "description": "Retrieve the ID of the authenticated account associated with the provided credentials. This is useful when you have an API key or access token but do not yet know the corresponding accountId.", - "parameters": [], - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "responses": { - "200": { - "description": "Account ID retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetAccountIdResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - } - } - } - }, - "/api/accounts": { - "post": { - "description": "Create a new account or retrieve an existing account by email or wallet address. If an account with the provided email or wallet already exists, returns that account. Otherwise creates a new account and initializes credits.", - "requestBody": { - "description": "Account credentials to create or lookup", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateAccountRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Account created or retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountDataResponse" - } - } - } - }, - "400": { - "description": "Bad request - failed to create account", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - } - } - }, - "patch": { - "description": "Update an existing account's profile information including name, organization, image, instruction, job title, role type, company name, and knowledges. Requires authentication via x-api-key or Authorization Bearer token. The authenticated account may update itself or a permitted account_id override.", - "requestBody": { - "description": "Account fields to update", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateAccountRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Account updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountDataResponse" - } - } - } - }, - "400": { - "description": "Bad request - account not found or update failed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - account override not permitted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - } - } - } - }, - "/api/accounts/artists": { - "post": { - "description": "Add an artist to an account's list of associated artists. If the artist is already associated with the account, returns success without modification.", - "requestBody": { - "description": "Account and artist identifiers", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddArtistToAccountRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Artist added to account successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddArtistSuccessResponse" - } - } - } - }, - "400": { - "description": "Bad request - account not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - } - } - } - }, - "/api/artists": { - "get": { - "description": "Retrieve artists accessible to the authenticated account. The account is derived from the API key or Bearer token. When org_id is omitted, returns only the account's own artists. Pass org_id to view artists in a specific organization. Pass account_id to filter to a specific account the API key has access to.", - "parameters": [ - { - "name": "account_id", - "in": "query", - "description": "Filter to a specific account's artists. Only applicable when the authenticated account has access to multiple accounts via organization membership.", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "org_id", - "in": "query", - "description": "Filter to artists in a specific organization. When omitted, returns only personal (non-organization) artists.", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Artists retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistsResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistsErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - missing or invalid authentication" - }, - "403": { - "description": "Forbidden - account_id is not accessible with the provided credentials" - } - } - }, - "post": { - "description": "Create a new artist account. The artist can optionally be linked to an organization.", - "requestBody": { - "description": "Artist creation parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateArtistRequest" - } - } - } - }, - "responses": { - "201": { - "description": "Artist created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateArtistResponse" - } - } - } - }, - "400": { - "description": "Bad request - validation error or invalid JSON", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateArtistError" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - } - }, - "/api/artist/segments": { - "get": { - "description": "Retrieve all segments associated with an artist. This endpoint should be called before using the Segment Fans endpoint to obtain the necessary segment IDs. Supports pagination.", - "parameters": [ - { - "name": "artist_account_id", - "in": "query", - "description": "The unique identifier of the artist account to fetch segments for", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "page", - "in": "query", - "description": "The page number to retrieve (default: 1)", - "required": false, - "schema": { - "type": "integer", - "default": 1 - } - }, - { - "name": "limit", - "in": "query", - "description": "The number of records per page (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "default": 20, - "maximum": 100 - } - } - ], - "responses": { - "200": { - "description": "Segments retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistSegmentsResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistSegmentsErrorResponse" - } - } - } - } - } - } - }, - "/api/artist/socials": { - "get": { - "description": "Retrieve all social media profiles associated with an artist. This endpoint should be called before using the Social Posts endpoint to obtain the necessary social IDs.", - "parameters": [ - { - "name": "artist_account_id", - "in": "query", - "description": "The unique identifier of the artist account to fetch social profiles for", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Social profiles retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistSocialsResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistSocialsErrorResponse" - } - } - } - } - } - } - }, - "/api/artist/socials/scrape": { - "post": { - "description": "Trigger scrape jobs for all social profiles linked to an artist. Provide an artist_account_id, and the API will look up the artist's socials and invoke a scraping job for each social profile. Each scrape returns Apify run metadata so you can poll for status and retrieve results.", - "requestBody": { - "description": "Artist to scrape socials for", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistSocialsScrapeRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Scrape jobs triggered successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistSocialsScrapeResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistSocialsErrorResponse" - } - } - } - } - } - } - }, - "/api/artist-profile": { - "get": { - "description": "Retrieve comprehensive profile information for an artist across all connected social media platforms, including profile details and post metrics.", - "parameters": [ - { - "name": "artist_account_id", - "in": "query", - "description": "The unique identifier of the artist account to fetch profile data for", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Artist profile retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistProfileResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistProfileErrorResponse" - } - } - } - } - } - } - }, - "/api/segment/fans": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Retrieve all social profiles from fans within a specific segment. This endpoint should be called after obtaining segment IDs from the Artist Segments endpoint. Supports pagination for large fan lists.", - "parameters": [ - { - "name": "segment_id", - "in": "query", - "description": "The unique identifier of the segment to fetch fans for", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "page", - "in": "query", - "description": "The page number to retrieve (default: 1)", - "required": false, - "schema": { - "type": "integer", - "default": 1 - } - }, - { - "name": "limit", - "in": "query", - "description": "The number of records per page (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "default": 20, - "maximum": 100 - } - } - ], - "responses": { - "200": { - "description": "Segment fans retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SegmentFansResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SegmentFansErrorResponse" - } - } - } - } - } - } - }, - "/api/fans": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Retrieve all social profiles from fans of an artist across all platforms. This endpoint aggregates fan data from all connected social media platforms. Supports pagination for large fan lists.", - "parameters": [ - { - "name": "artist_account_id", - "in": "query", - "description": "The unique identifier of the artist account to fetch fans for", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "page", - "in": "query", - "description": "The page number to retrieve (default: 1)", - "required": false, - "schema": { - "type": "integer", - "default": 1 - } - }, - { - "name": "limit", - "in": "query", - "description": "The number of records per page (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "default": 20, - "maximum": 100 - } - } - ], - "responses": { - "200": { - "description": "Artist fans retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistFansResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistFansErrorResponse" - } - } - } - } - } - } - }, - "/api/posts": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Retrieve all social media posts from an artist across all platforms. This endpoint aggregates posts from all connected social media profiles for the specified artist. Supports pagination for large post collections.", - "parameters": [ - { - "name": "artist_account_id", - "in": "query", - "description": "The unique identifier of the artist account to fetch posts for", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "page", - "in": "query", - "description": "The page number to retrieve (default: 1)", - "required": false, - "schema": { - "type": "integer", - "default": 1 - } - }, - { - "name": "limit", - "in": "query", - "description": "The number of records per page (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "default": 20, - "maximum": 100 - } - } - ], - "responses": { - "200": { - "description": "Artist posts retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistPostsResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArtistPostsErrorResponse" - } - } - } - } - } - } - }, - "/api/comments": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Retrieve comments associated with an artist or a specific post, with support for pagination. This endpoint returns raw comment data including the comment text, associated post, and commenter's social profile reference.", - "parameters": [ - { - "name": "artist_account_id", - "in": "query", - "description": "The unique identifier of the artist account to fetch comments for", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "post_id", - "in": "query", - "description": "Filter comments by specific post", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number for pagination (default: 1)", - "required": false, - "schema": { - "type": "integer", - "default": 1 - } - }, - { - "name": "limit", - "in": "query", - "description": "Number of comments per page (default: 10)", - "required": false, - "schema": { - "type": "integer", - "default": 10 - } - } - ], - "responses": { - "200": { - "description": "Comments retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CommentsResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CommentsErrorResponse" - } - } - } - } - } - } - }, - "/api/post/comments": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Retrieve comments for a specific social media post. This endpoint should be called after obtaining post IDs from the Social Posts endpoint. Returns detailed information about each commenter including their profile data, follower counts, and geographic region.", - "parameters": [ - { - "name": "post_id", - "in": "query", - "description": "The unique identifier of the post to fetch comments for", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "page", - "in": "query", - "description": "The page number to retrieve (default: 1)", - "required": false, - "schema": { - "type": "integer", - "default": 1 - } - }, - { - "name": "limit", - "in": "query", - "description": "The number of records per page (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "default": 20, - "maximum": 100 - } - } - ], - "responses": { - "200": { - "description": "Post comments retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PostCommentsResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PostCommentsErrorResponse" - } - } - } - } - } - } - }, - "/api/chats": { - "get": { - "description": "Retrieve chat rooms (conversations) for the authenticated account. If the account has access to organizations, pass account_id to filter to a specific account within those organizations. Optionally filter by an artist_account_id. The endpoint returns metadata about each room, including the topic, associated artist, and last updated timestamp.", - "parameters": [ - { - "name": "artist_account_id", - "in": "query", - "description": "Optional. Filter chats to only include those for the specified artist.", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "account_id", - "in": "query", - "description": "Filter to a specific account. Only applicable when the authenticated account has access to multiple accounts via organization membership.", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Chats retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetChatsResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid query parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetChatsErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "403": { - "description": "Forbidden - account_id is not a member of the organization or account tried to filter by an account_id they don't have access to", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - }, - "post": { - "description": "Create a new chat room. Optionally associate it with an artist and/or provide a client-generated chat ID. Pass accountId to create a chat on behalf of a specific account the API key has access to.", - "requestBody": { - "description": "Chat creation parameters", - "required": false, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateChatRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Chat created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateChatResponse" - } - } - } - }, - "400": { - "description": "Bad request - failed to create chat", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateChatErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - API key does not have access to the specified accountId", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateChatErrorResponse" - } - } - } - } - } - }, - "patch": { - "description": "Update a chat room's topic (display name). The chatId is required; the topic field will be updated. Topic must be between 3 and 50 characters.", - "requestBody": { - "description": "Chat fields to update", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateChatRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Chat updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateChatResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid parameters or validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateChatErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "403": { - "description": "Forbidden - API key does not have access to this chat", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "404": { - "description": "Not found - chat room does not exist", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateChatErrorResponse" - } - } - } - } - } - }, - "delete": { - "description": "Delete a chat room by ID. This operation also removes related room records (memory emails, memories, room-report links, and segment-room links) before deleting the room itself.", - "requestBody": { - "description": "Chat deletion parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteChatRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Chat deleted successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteChatResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid parameters or validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteChatErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "403": { - "description": "Forbidden - API key does not have access to this chat", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "404": { - "description": "Not found - chat room does not exist", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteChatErrorResponse" - } - } - } - }, - "500": { - "description": "Server error - failed to delete chat", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteChatErrorResponse" - } - } - } - } - } - } - }, - "/api/chats/{id}/artist": { - "get": { - "description": "Retrieve the artist associated with a specific chat room. Returns 404 if the chat does not exist or is not accessible by the authenticated caller.", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "The unique identifier (UUID) of the chat room.", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Chat artist resolved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetChatArtistResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid chat id", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetChatArtistErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "404": { - "description": "Not found - chat does not exist or is not accessible", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetChatArtistErrorResponse" - } - } - } - } - } - } - }, - "/api/chats/{id}/segment": { - "get": { - "description": "Retrieve the segment associated with a specific chat room. Returns 404 if the chat does not exist or is not accessible by the authenticated caller.", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "The unique identifier (UUID) of the chat room.", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Chat segment resolved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetChatSegmentResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid chat id", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetChatSegmentErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "404": { - "description": "Not found - chat does not exist or is not accessible", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetChatSegmentErrorResponse" - } - } - } - } - } - } - }, - "/api/chats/{id}/messages": { - "get": { - "description": "Retrieve all messages (memories) for a specific chat room in chronological order.", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "The unique identifier (UUID) of the chat room.", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Messages retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetChatMessagesResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid chat id", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetChatMessagesErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "403": { - "description": "Forbidden - caller does not have access to this chat", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "404": { - "description": "Not found - chat does not exist or is not accessible", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetChatMessagesErrorResponse" - } - } - } - }, - "500": { - "description": "Server error - failed to retrieve messages", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetChatMessagesErrorResponse" - } - } - } - } - } - } - }, - "/api/chats/{id}/messages/copy": { - "post": { - "description": "Copy all messages from the source chat (`id` path param) to a target chat (`targetChatId` in request body). By default, existing target messages are cleared before copy.", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "The source chat room UUID.", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "requestBody": { - "description": "Copy target options", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CopyChatMessagesRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Messages copied successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CopyChatMessagesResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid payload or chat identifiers", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CopyChatMessagesErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "403": { - "description": "Forbidden - caller lacks access to source or target chat", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CopyChatMessagesErrorResponse" - } - } - } - }, - "404": { - "description": "Not found - source or target chat does not exist", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CopyChatMessagesErrorResponse" - } - } - } - }, - "500": { - "description": "Server error - failed to copy messages", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CopyChatMessagesErrorResponse" - } - } - } - } - } - } - }, - "/api/chats/{id}/messages/trailing": { - "delete": { - "description": "Delete all messages in a chat from a given message onward (inclusive), identified by `from_message_id`.", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "The unique identifier (UUID) of the chat room.", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "from_message_id", - "in": "query", - "description": "The message UUID from which trailing messages should be deleted (inclusive).", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Trailing messages deleted successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteTrailingChatMessagesResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid or missing query/path parameters or message does not belong to chat", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteTrailingChatMessagesErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteTrailingChatMessagesErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - access denied to this chat", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteTrailingChatMessagesErrorResponse" - } - } - } - }, - "404": { - "description": "Not found - chat or message does not exist", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteTrailingChatMessagesErrorResponse" - } - } - } - }, - "500": { - "description": "Server error - failed to delete trailing messages", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteTrailingChatMessagesErrorResponse" - } - } - } - } - } - } - }, - "/api/chats/compact": { - "post": { - "description": "Compact one or more chat conversations into summarized versions. This reduces the size of chat history while preserving key information. Optionally provide a prompt to control what information gets preserved in the compacted summary.", - "requestBody": { - "description": "Chat compaction parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CompactChatsRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Chats compacted successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CompactChatsResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "404": { - "description": "Not found - one or more chat IDs do not exist", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - } - }, - "/api/chat/generate": { - "post": { - "servers": [ - { - "url": "https://recoup-api.vercel.app" - } - ], - "description": "Generate AI-powered text responses using the Recoup chat system. This endpoint processes chat requests and returns generated text along with metadata about the generation process.", - "security": [ - { - "apiKeyAuth": [] - } - ], - "requestBody": { - "description": "Chat generation request", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChatGenerateRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Chat generated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChatGenerateResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChatGenerateErrorResponse" - } - } - } - } - } - } - }, - "/api/chat": { - "post": { - "servers": [ - { - "url": "https://recoup-api.vercel.app" - } - ], - "description": "Stream AI-powered chat responses using the Recoup chat system. This endpoint mirrors the request payload of the Chat Generate API but returns a streaming response compatible with the Vercel AI SDK `createUIMessageStreamResponse`. The stream emits UI message parts encoded as data chunks that can be parsed with `createUIMessageStreamParser`.", - "security": [ - { - "apiKeyAuth": [] - } - ], - "requestBody": { - "description": "Chat stream request", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChatStreamRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Streaming response with UI message parts. Events include: message-start (assistant begins message), message-delta (incremental updates), message-end (assistant finishes message), error (stream error), and metadata (usage data).", - "content": { - "text/event-stream": { - "schema": { - "type": "string", - "description": "Server-Sent Events stream containing UI message parts" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChatStreamErrorResponse" - } - } - } - } - } - } - }, - "/api/organizations": { - "get": { - "description": "Retrieve all organizations that the authenticated account belongs to. Pass account_id to retrieve organizations for a specific account the API key has access to.", - "parameters": [ - { - "name": "account_id", - "in": "query", - "description": "Filter to a specific account. Only applicable when the authenticated account has access to multiple accounts via organization membership.", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Organizations retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetOrganizationsResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid query parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OrganizationsErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "403": { - "description": "Forbidden - account_id is not a member of the organization or account tried to filter by an account_id they don't have access to", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - }, - "post": { - "description": "Create a new organization. The creator is automatically added as a member of the organization.", - "requestBody": { - "description": "Organization creation parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateOrganizationRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Organization created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateOrganizationResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OrganizationsErrorResponse" - } - } - } - } - } - } - }, - "/api/organizations/artists": { - "post": { - "description": "Add an artist to an organization. This allows organization members to access and manage the artist. This endpoint is idempotent - calling it multiple times with the same artistId and organizationId will not create duplicate records.", - "requestBody": { - "description": "Artist-organization association parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddArtistToOrganizationRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Artist added to organization successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddArtistToOrganizationResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OrganizationsErrorResponse" - } - } - } - } - } - } - }, - "/api/spotify/search": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Search for artists, albums, tracks, and playlists using the Spotify API. This endpoint is a proxy to the official Spotify Search API.", - "parameters": [ - { - "name": "q", - "in": "query", - "description": "The search query keywords and optional field filters", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "type", - "in": "query", - "description": "A comma-separated list of item types to search across: album, artist, playlist, track, show, episode, audiobook", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "market", - "in": "query", - "description": "An ISO 3166-1 alpha-2 country code or 'from_token'", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Maximum number of results to return (default: 20, min: 1, max: 50)", - "required": false, - "schema": { - "type": "integer", - "default": 20, - "minimum": 1, - "maximum": 50 - } - }, - { - "name": "offset", - "in": "query", - "description": "The index of the first result to return (default: 0, max: 10000)", - "required": false, - "schema": { - "type": "integer", - "default": 0, - "maximum": 10000 - } - } - ], - "responses": { - "200": { - "description": "Search results retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SpotifySearchResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SpotifyErrorResponse" - } - } - } - } - } - } - }, - "/api/spotify/artist/": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Get Spotify catalog information for a single artist identified by their unique Spotify ID.", - "parameters": [ - { - "name": "id", - "in": "query", - "description": "The Spotify ID of the artist", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Artist retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SpotifyGetArtistResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SpotifyErrorResponse" - } - } - } - } - } - } - }, - "/api/spotify/artist/albums": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Get Spotify catalog information about an artist's albums.", - "parameters": [ - { - "name": "id", - "in": "query", - "description": "The Spotify ID of the artist", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "include_groups", - "in": "query", - "description": "A comma-separated list of keywords to filter the response. Valid values are: album, single, appears_on, compilation", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "market", - "in": "query", - "description": "An ISO 3166-1 alpha-2 country code. If specified, only content available in that market will be returned", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "The maximum number of items to return (default: 20, min: 1, max: 50)", - "required": false, - "schema": { - "type": "integer", - "default": 20, - "minimum": 1, - "maximum": 50 - } - }, - { - "name": "offset", - "in": "query", - "description": "The index of the first item to return (default: 0)", - "required": false, - "schema": { - "type": "integer", - "default": 0 - } - } - ], - "responses": { - "200": { - "description": "Artist albums retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SpotifyArtistAlbumsResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SpotifyErrorResponse" - } - } - } - } - } - } - }, - "/api/spotify/artist/topTracks": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Get an artist's top tracks by country.", - "parameters": [ - { - "name": "id", - "in": "query", - "description": "The Spotify ID of the artist", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "market", - "in": "query", - "description": "An ISO 3166-1 alpha-2 country code. If provided, only tracks available in that market are returned", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Artist top tracks retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SpotifyArtistTopTracksResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SpotifyErrorResponse" - } - } - } - } - } - } - }, - "/api/spotify/album": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Get Spotify catalog information for a single album.", - "parameters": [ - { - "name": "id", - "in": "query", - "description": "The Spotify ID of the album", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "market", - "in": "query", - "description": "An ISO 3166-1 alpha-2 country code. If provided, only content available in that market is returned", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Album retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SpotifyAlbum" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SpotifyErrorResponse" - } - } - } - } - } - } - }, - "/api/instagram/comments": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Fetch Instagram comments for multiple post URLs using Apify's Instagram Comment Scraper. The actual comment data will be available in the Apify dataset after the run completes.", - "parameters": [ - { - "name": "postUrls", - "in": "query", - "description": "Array of Instagram post URLs to fetch comments for", - "required": true, - "schema": { - "type": "array", - "items": { - "type": "string" - } - }, - "style": "form", - "explode": true - }, - { - "name": "resultsLimit", - "in": "query", - "description": "Maximum number of comments to fetch (default: 10000)", - "required": false, - "schema": { - "type": "integer", - "default": 10000 - } - }, - { - "name": "isNewestComments", - "in": "query", - "description": "Whether to fetch newest comments first. Set to true for newest first, false for oldest first, or omit for platform default sorting", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "Apify scraper run started successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApifyRunResult" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InstagramErrorResponse" - } - } - } - } - } - } - }, - "/api/instagram/profiles": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Fetch Instagram profile information for multiple handles using Apify's Instagram Profile Scraper. The actual profile data will be available in the Apify dataset after the run completes.", - "parameters": [ - { - "name": "handles", - "in": "query", - "description": "Array of Instagram handles to fetch profiles for", - "required": true, - "schema": { - "type": "array", - "items": { - "type": "string" - } - }, - "style": "form", - "explode": true - } - ], - "responses": { - "200": { - "description": "Apify scraper run started successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApifyRunResult" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InstagramErrorResponse" - } - } - } - } - } - } - }, - "/api/apify/scraper": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Check the status and retrieve results from Apify scraper runs. This endpoint uses the Apify API Client to fetch the current status of a scraper run and its results if available. Use the runId returned from endpoints like Instagram Comments, Instagram Profiles, Social Scrape, or Artist Socials Scrape to poll for results.", - "parameters": [ - { - "name": "runId", - "in": "query", - "description": "The ID of the Apify run to check status for. This is returned when starting a scrape via Instagram Comments, Instagram Profiles, Social Scrape, or Artist Socials Scrape endpoints.", - "required": true, - "schema": { - "type": "string" - }, - "example": "abc123xyz" - } - ], - "responses": { - "200": { - "description": "Scraper run status retrieved successfully. Returns status info for in-progress runs, or status info plus data for completed runs.", - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/ApifyScraperInProgressResponse" - }, - { - "$ref": "#/components/schemas/ApifyScraperCompletedResponse" - } - ] - } - } - } - }, - "400": { - "description": "Bad request - missing required runId parameter", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApifyScraperErrorResponse" - } - } - } - }, - "500": { - "description": "Server error - failed to fetch run status from Apify", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApifyScraperErrorResponse" - } - } - } - } - } - } - }, - "/api/sandboxes": { - "get": { - "description": "List all sandboxes associated with the authenticated account and their current statuses. Returns sandbox details including lifecycle state, timeout remaining, and creation timestamp. Pass account_id to retrieve sandboxes for a specific account the API key has access to. Authentication is handled via the x-api-key header or Authorization Bearer token.", - "parameters": [ - { - "name": "sandbox_id", - "in": "query", - "required": false, - "description": "Filter by a specific sandbox ID. When provided, returns only the sandbox matching this ID. Must be a sandbox that your account or organization is an admin of.", - "schema": { - "type": "string", - "example": "sbx_abc123def456" - } - }, - { - "name": "account_id", - "in": "query", - "description": "Filter to a specific account. Only applicable when the authenticated account has access to multiple accounts via organization membership.", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Sandboxes retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - account_id is not a member of the organization or account tried to filter by an account_id they don't have access to", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - } - } - }, - "post": { - "description": "Create a new ephemeral sandbox environment. Optionally executes a command or an OpenCode prompt if provided. Sandboxes are isolated Linux microVMs that can be used to evaluate account-generated code, run AI agent output safely, or execute reproducible tasks. The sandbox will automatically stop after the timeout period. If no command or prompt is provided, the sandbox is created without triggering any background task. Use the prompt parameter as a shortcut to run `opencode run \"\"` in the sandbox. Pass account_id to create a sandbox for a specific account the API key has access to. Authentication is handled via the x-api-key header or Authorization Bearer token.", - "requestBody": { - "description": "Optional command execution parameters. If command and prompt are both omitted, sandbox is created without running any command. Use prompt as a shortcut for running OpenCode.", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSandboxRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Sandbox created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxesResponse" - } - } - } - }, - "400": { - "description": "Bad request - failed to create sandbox", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - account_id is not a member of the organization or account tried to use an account_id they don't have access to", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - } - } - }, - "patch": { - "description": "Set a custom snapshot ID for an account. By default, updates the key owner's account. Pass account_id to target a specific account the API key has access to. This allows accounts to use a specific sandbox snapshot when creating new sandboxes, enabling reproducible environments with pre-configured tools, dependencies, and files.", - "requestBody": { - "description": "Snapshot configuration parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateSnapshotRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Snapshot ID updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateSnapshotResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid snapshot ID", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - account_id is not a member of the organization or account tried to use an account_id they don't have access to", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - } - } - }, - "delete": { - "description": "Delete a sandbox environment for the authenticated account. This permanently deletes the associated GitHub repository and removes the account's snapshot record from the database. By default, deletes the sandbox for the key owner's account. Pass account_id to target a specific account the API key has access to. Authentication is handled via the x-api-key header or Authorization Bearer token.", - "requestBody": { - "description": "Optional account targeting parameters", - "required": false, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteSandboxRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Sandbox deleted successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteSandboxResponse" - } - } - } - }, - "400": { - "description": "Bad request - failed to delete sandbox", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - account_id is not a member of the organization or account tried to use an account_id they don't have access to", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - } - } - } - }, - "/api/sandboxes/setup": { - "post": { - "description": "Triggers the setup-sandbox background task to create a personal sandbox, provision a GitHub repo, take a snapshot, and shut down. By default, sets up the sandbox for the key owner's account. Pass account_id to target a specific account the API key has access to. Authentication is handled via the x-api-key header or Authorization Bearer token.", - "requestBody": { - "description": "Optional account targeting parameters", - "required": false, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetupSandboxRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Setup task triggered successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetupSandboxResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid account_id format", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - } - } - } - }, - "/api/sandboxes/file": { - "get": { - "description": "Retrieve the raw contents of a file from the authenticated account's sandbox GitHub repository. Resolves the github_repo from the [account's snapshot](/api-reference/sandboxes/list), then fetches the file at the specified path from the repository's main branch. Authentication is handled via the x-api-key header or Authorization Bearer token.", - "parameters": [ - { - "name": "path", - "in": "query", - "required": true, - "description": "The file path within the repository (e.g. \"src/index.ts\" or \"README.md\").", - "schema": { - "type": "string", - "example": "src/index.ts" - } - } - ], - "responses": { - "200": { - "description": "File contents retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxFileResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing or invalid path parameter", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - account does not have access", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - }, - "404": { - "description": "Not found - no snapshot, no github_repo, or file not found in repository", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - } - } - } - }, - "/api/sandboxes/files": { - "post": { - "description": "Upload one or more files to the authenticated account's sandbox GitHub repository. Accepts an array of file URLs and commits each file to the specified directory path within the repository. Supports submodule resolution — if the target path falls within a git submodule, the file is committed to the submodule's repository. Authentication is handled via the x-api-key header or Authorization Bearer token.", - "requestBody": { - "description": "JSON body containing file URLs and target path", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UploadSandboxFilesRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Files uploaded successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UploadSandboxFilesResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing files or invalid path", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - account does not have access", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - }, - "404": { - "description": "Not found - no snapshot or no github_repo configured", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxErrorResponse" - } - } - } - } - } - } - }, - "/api/x/search": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Search for tweets using the Twitter Search API, powered by agent-twitter-client (no Twitter API key required). Supports various search modes including Top, Latest, Photos, Videos, and Users.", - "parameters": [ - { - "name": "query", - "in": "query", - "description": "The search query. Any Twitter-compatible query format can be used (e.g., '#nodejs', 'from:username', etc.)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "maxTweets", - "in": "query", - "description": "The maximum number of tweets to return", - "required": true, - "schema": { - "type": "integer" - } - }, - { - "name": "searchMode", - "in": "query", - "description": "The category filter to apply to the search", - "required": false, - "schema": { - "type": "string", - "enum": [ - "Top", - "Latest", - "Photos", - "Videos", - "Users" - ], - "default": "Latest" - } - } - ], - "responses": { - "200": { - "description": "Tweets retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TwitterSearchResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TwitterErrorResponse" - } - } - } - } - } - } - }, - "/api/x/trends": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Retrieve the current trending topics from Twitter using the getTrends method from agent-twitter-client (no Twitter API key required).", - "responses": { - "200": { - "description": "Trends retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TwitterTrendsResponse" - } - } - } - }, - "400": { - "description": "Bad request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TwitterErrorResponse" - } - } - } - } - } - } - }, - "/api/social/scrape": { - "post": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Trigger a social profile scraping job for a given social_id. Use the Get Artist Socials endpoint first to retrieve the social_id values. The response returns Apify run metadata for polling status and retrieving results via the Apify Scraper Results API.", - "requestBody": { - "description": "Social profile to scrape", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SocialScrapeRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Scrape job triggered successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApifyRunResult" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SocialErrorResponse" - } - } - } - } - } - } - }, - "/api/social/posts": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Retrieve all social media posts from a specific social profile. Call the Artist Socials endpoint first to obtain social IDs.", - "parameters": [ - { - "name": "social_id", - "in": "query", - "description": "The unique identifier (UUID) of the social profile to fetch posts for", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "latestFirst", - "in": "query", - "description": "Sort posts by most recent first (default: true)", - "required": false, - "schema": { - "type": "boolean", - "default": true - } - }, - { - "name": "page", - "in": "query", - "description": "The page number to retrieve (default: 1)", - "required": false, - "schema": { - "type": "integer", - "default": 1 - } - }, - { - "name": "limit", - "in": "query", - "description": "The number of records per page (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "default": 20, - "maximum": 100 - } - } - ], - "responses": { - "200": { - "description": "Posts retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SocialPostsResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SocialErrorResponse" - } - } - } - } - } - } - }, - "/api/image/generate": { - "get": { - "servers": [ - { - "url": "https://recoup-api.vercel.app" - } - ], - "description": "Generate high-quality images using AI models. Images are automatically stored on Arweave and include In Process moment metadata for provenance and ownership tracking.", - "parameters": [ - { - "name": "prompt", - "in": "query", - "description": "Text description of the image you want to generate", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "account_id", - "in": "query", - "description": "The unique identifier of the account generating the image", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Image generated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ImageGenerationResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required parameters or invalid input", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ImageGenerationErrorResponse" - } - } - } - } - } - } - }, - "/api/transcribe": { - "post": { - "description": "Transcribe audio files using OpenAI Whisper. The API saves both the original audio file and the generated markdown transcript to the customer's files in Supabase Storage.", - "requestBody": { - "description": "Audio transcription request", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TranscribeAudioRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Audio transcribed successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TranscribeAudioResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required fields or invalid audio URL", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TranscribeAudioErrorResponse" - } - } - } - }, - "413": { - "description": "Audio file exceeds the 25MB limit", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TranscribeAudioErrorResponse" - } - } - } - }, - "429": { - "description": "Rate limit exceeded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TranscribeAudioErrorResponse" - } - } - } - }, - "500": { - "description": "Server error - OpenAI API key not configured", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TranscribeAudioErrorResponse" - } - } - } - } - } - } - }, - "/api/songs": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Retrieve songs from the database with optional filtering by ISRC (International Standard Recording Code) or artist account. This endpoint joins the songs table with song_artists and accounts tables to provide comprehensive song information.", - "parameters": [ - { - "name": "isrc", - "in": "query", - "description": "International Standard Recording Code to filter by specific song", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "artist_account_id", - "in": "query", - "description": "Artist account ID to filter songs by artist", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Songs retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SongsResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SongsErrorResponse" - } - } - } - }, - "404": { - "description": "No songs found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SongsErrorResponse" - } - } - } - } - } - }, - "post": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Bulk create or fetch songs by ISRC. For each song, the API attempts to look up metadata via internal search. If no data is found, optional fallback fields (name, album, notes, artists) are used.", - "requestBody": { - "description": "Array of songs to create or fetch", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSongsRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Songs created or fetched successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SongsResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SongsErrorResponse" - } - } - } - } - } - } - }, - "/api/catalogs": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Retrieve catalogs associated with a specific account. The endpoint joins account_catalogs with catalogs to return catalog metadata for the specified account.", - "parameters": [ - { - "name": "account_id", - "in": "query", - "description": "The unique identifier of the account to query", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Catalogs retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogsResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing or invalid account_id", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogsErrorResponse" - } - } - } - }, - "404": { - "description": "Account not found or no catalogs found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogsErrorResponse" - } - } - } - } - } - }, - "post": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Create new catalogs or link existing catalogs to an account. If catalog_id is provided, links the existing catalog. If name is provided without catalog_id, creates a new catalog. If both are provided, catalog_id takes priority.", - "requestBody": { - "description": "Array of catalogs to create or link", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateCatalogsRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Catalogs created or linked successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogsResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid parameters or catalog_id not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogsErrorResponse" - } - } - } - } - } - }, - "delete": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Unlink catalogs from an account. If no other accounts are linked to a catalog after removal, the catalog is automatically deleted (cascading to catalog_songs). Otherwise, only the account-catalog relationship is removed.", - "requestBody": { - "description": "Array of catalog-account pairs to remove", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteCatalogsRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Catalogs unlinked successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogsResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing catalog_id or account_id", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogsErrorResponse" - } - } - } - } - } - } - }, - "/api/catalogs/songs": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Retrieve songs within a specific catalog with pagination support. This endpoint joins catalog_songs with songs, song_artists, and accounts to provide comprehensive song information for a given catalog.", - "parameters": [ - { - "name": "catalog_id", - "in": "query", - "description": "The unique identifier of the catalog to query songs for", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "artistName", - "in": "query", - "description": "Optional. Filters songs to only include those with matching artist name", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number for pagination (default: 1)", - "required": false, - "schema": { - "type": "integer", - "default": 1 - } - }, - { - "name": "limit", - "in": "query", - "description": "Number of songs per page (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "default": 20, - "maximum": 100 - } - } - ], - "responses": { - "200": { - "description": "Catalog songs retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogSongsResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing or invalid catalog_id", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogSongsErrorResponse" - } - } - } - }, - "404": { - "description": "Catalog not found or no songs in catalog", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogSongsErrorResponse" - } - } - } - } - } - }, - "post": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Batch add songs to a catalog by ISRC. For each song, the API attempts to look up metadata via internal search. If no data is found, optional fallback fields (name, album, notes, artists) are used.", - "requestBody": { - "description": "Array of songs to add to catalog", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddCatalogSongsRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Songs added to catalog successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogSongsResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing required fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogSongsErrorResponse" - } - } - } - } - } - }, - "delete": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Batch remove songs from a catalog by ISRC. Deletes the relationship in catalog_songs for each catalog_id and ISRC pair.", - "requestBody": { - "description": "Array of songs to remove from catalog", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteCatalogSongsRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Songs removed from catalog successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogSongsResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing catalog_id or isrc", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatalogSongsErrorResponse" - } - } - } - } - } - } - }, - "/api/subscriptions": { - "get": { - "servers": [ - { - "url": "https://api.recoupable.com" - } - ], - "description": "Retrieve subscription information for an account. For accounts with enterprise plans, returns a simplified response indicating enterprise status. For standard accounts, returns the full Stripe subscription object.", - "parameters": [ - { - "name": "accountId", - "in": "query", - "description": "The unique identifier of the account to query", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Subscription information retrieved successfully", - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/SubscriptionResponse" - }, - { - "$ref": "#/components/schemas/EnterpriseSubscriptionResponse" - } - ] - } - } - } - }, - "400": { - "description": "Bad request - missing or invalid accountId", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SubscriptionErrorResponse" - } - } - } - }, - "404": { - "description": "Account not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SubscriptionErrorResponse" - } - } - } - } - } - } - }, - "/api/workspaces": { - "post": { - "description": "Create a new workspace account. Workspaces can optionally be linked to an organization.", - "requestBody": { - "description": "Workspace creation parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateWorkspaceRequest" - } - } - } - }, - "responses": { - "201": { - "description": "Workspace created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateWorkspaceResponse" - } - } - } - }, - "400": { - "description": "Bad request - validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing authentication", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "403": { - "description": "Forbidden - access denied to organization", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - } - }, - "/api/pulses": { - "get": { - "description": "Retrieve pulse information for the authenticated account. If the account has access to organizations, pass account_id to filter to a specific account within those organizations.", - "parameters": [ - { - "name": "account_id", - "in": "query", - "description": "Filter to a specific account. Only applicable when the authenticated account has access to multiple accounts via organization membership.", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "active", - "in": "query", - "description": "Filter by active status. Set to 'true' to return only active pulses, 'false' for inactive pulses. If not provided, returns all pulses regardless of active status.", - "required": false, - "schema": { - "type": "string", - "enum": [ - "true", - "false" - ] - } - } - ], - "responses": { - "200": { - "description": "Pulses retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PulsesResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid query parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "403": { - "description": "Forbidden - account_id is not a member of the organization or account tried to filter by an account_id they don't have access to", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - }, - "patch": { - "description": "Update the pulse settings for an account. Use this to enable or disable the pulse. Returns an array of pulses for consistency with the GET endpoint.", - "requestBody": { - "description": "Pulse fields to update", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdatePulseRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Pulse updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PulsesResponse" - } - } - } - }, - "400": { - "description": "Bad request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - } - }, - "/api/connectors": { - "get": { - "description": "List available connectors and their connection status. Returns all supported third-party integrations (e.g., Google Sheets, TikTok) along with whether they are currently connected.", - "parameters": [ - { - "name": "account_id", - "in": "query", - "description": "Optional account ID to get connectors for a different account (e.g., an artist, workspace, or organization). The authenticated account must have access to the specified account. Omit to get your own account's connectors.", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "Connectors retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConnectorsResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid account_id format", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "403": { - "description": "Forbidden - no access to the specified account", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - }, - "delete": { - "description": "Disconnect a connected account from a third-party service. This revokes the OAuth connection and removes stored credentials.", - "requestBody": { - "description": "Connection to disconnect", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DisconnectConnectorRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Connector disconnected successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DisconnectConnectorResponse" - } - } - } - }, - "400": { - "description": "Bad request - missing or invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "403": { - "description": "Forbidden - no access to the specified account or connection", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - }, - "post": { - "description": "Generate an OAuth authorization URL for connecting a third-party service. Redirect to the returned URL to complete the OAuth flow.", - "requestBody": { - "description": "Authorization request details", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthorizeConnectorRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Authorization URL generated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthorizeConnectorResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid connector or parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "401": { - "description": "Unauthorized - invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "403": { - "description": "Forbidden - no access to the specified account", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - } - }, - "/api/content": { - "patch": { - "description": "Apply edits to content — trim, crop, resize, overlay text, or add an audio track. Accepts video, image, or audio input. Pass a `template` for a preset edit pipeline, or build your own with an `operations` array.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Edit parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateEditRequest" - } - } - } - }, - "responses": { - "202": { - "description": "Edit task triggered successfully. Poll via [GET /api/tasks/runs](/api-reference/tasks/runs) using the returned `runId`.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateEditResponse" - } - } - } - }, - "400": { - "description": "Validation failed — invalid or missing request body fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - } - } - } - }, - "/api/content/create": { - "post": { - "description": "Trigger the content creation pipeline for an artist. Provide `artist_account_id` to identify the target artist. Validates the artist has all required files (face guide, songs) unless overridden via `songs` URLs or `images`, then triggers a background task that generates a short-form video. Returns `runIds` — an array of run IDs that can each be polled via [GET /api/tasks/runs](/api-reference/tasks/runs).", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Content creation parameters including the target artist and optional template/workflow settings", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateRequest" - } - } - } - }, - "responses": { - "202": { - "description": "Pipeline triggered successfully. Returns `runIds` — an array of run IDs. Poll each via [GET /api/tasks/runs](/api-reference/tasks/runs) to check progress.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateResponse" - } - } - } - }, - "400": { - "description": "Validation failed — missing artist identifier, artist is missing required files, or template not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "404": { - "description": "Artist not found — the provided artist_account_id does not match any artist", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - } - } - } - }, - "/api/content/templates": { - "get": { - "description": "List all available content creation templates. Templates are optional — every content primitive works without one. When you do use a template, it provides a complete creative recipe: image prompts, video motion config, caption style rules, and edit operations. Returns template ID and description only — enough to pick the right one.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "responses": { - "200": { - "description": "Templates retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentTemplatesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - } - } - } - }, - "/api/content/templates/{id}": { - "get": { - "description": "Get the full configuration for a specific content creation template. Returns the complete creative recipe including image prompts, video motion config, caption style rules, and edit operations.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Template identifier", - "required": true, - "schema": { - "type": "string", - "example": "artist-caption-bedroom" - } - } - ], - "responses": { - "200": { - "description": "Template detail retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentTemplateDetail" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "404": { - "description": "Template not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "status": { - "type": "string", - "example": "error" - }, - "error": { - "type": "string", - "example": "Template not found" - } - } - } - } - } - } - } - } - }, - "/api/content/validate": { - "get": { - "description": "Check whether an artist has all the required files to run the content creation pipeline. Returns a structured report of each required and recommended file with its status. Required files must be present or the pipeline will fail. Recommended files improve output quality but are not strictly necessary. Provide `artist_account_id` as a query parameter.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "parameters": [ - { - "name": "artist_account_id", - "in": "query", - "description": "UUID of the artist account to validate. Use [GET /api/artists](/api-reference/artists/list) to find artist account IDs.", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "example": "1873859c-dd37-4e9a-9bac-80d3558527a9" - } - } - ], - "responses": { - "200": { - "description": "Validation completed. Check the `ready` field to determine if the artist can run the pipeline.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentValidateResponse" - } - } - } - }, - "400": { - "description": "Bad request — artist_account_id is required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "404": { - "description": "Artist not found — the provided artist_account_id does not match any artist", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - } - } - } - }, - "/api/content/estimate": { - "get": { - "description": "Estimate the cost of running the content creation pipeline. Calculates per-step and per-video costs based on current pricing. Supports comparing multiple workflow profiles (e.g., premium vs. budget) and projecting batch costs. This endpoint is informational only — it does not trigger any pipeline execution or spend credits.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "parameters": [ - { - "name": "lipsync", - "in": "query", - "description": "Which workflow to estimate. `false` for image-to-video, `true` for audio-to-video. If omitted, estimates the default image-to-video workflow.", - "required": false, - "schema": { - "type": "boolean", - "example": false - } - }, - { - "name": "batch", - "in": "query", - "description": "Number of videos to project costs for. Use this to answer questions like \"how much would 30 videos cost?\"", - "required": false, - "schema": { - "type": "integer", - "minimum": 1, - "default": 1, - "example": 1 - } - }, - { - "name": "compare", - "in": "query", - "description": "When `true`, returns estimates for all available workflow profiles (premium, budget, mid) for side-by-side comparison.", - "required": false, - "schema": { - "type": "boolean", - "default": false, - "example": false - } - } - ], - "responses": { - "200": { - "description": "Cost estimate calculated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentEstimateResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - } - } - } - }, - "/api/songs/analyze/presets": { - "get": { - "description": "Lists all available music analysis presets. Each preset is a curated prompt with optimized generation parameters for a specific use case (e.g. catalog metadata enrichment, sync licensing analysis, audience profiling). Requires authentication via API key or Bearer token.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "responses": { - "200": { - "description": "Presets listed successfully", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ] - }, - "presets": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Preset identifier to pass in the analyze request" - }, - "label": { - "type": "string", - "description": "Human-readable preset name" - }, - "description": { - "type": "string", - "description": "What this preset does" - }, - "requiresAudio": { - "type": "boolean", - "description": "Whether this preset needs an audio_url" - }, - "responseFormat": { - "type": "string", - "enum": [ - "json", - "text" - ], - "description": "Expected response format" - } - } - } - } - } - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key / Bearer token", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SongAnalyzeErrorResponse" - } - } - } - } - } - } - }, - "/api/songs/analyze": { - "post": { - "description": "Analyze music using a state-of-the-art Audio Language Model that listens directly to the audio waveform. Unlike text-based AI, this model processes the actual sound — identifying harmony, structure, timbre, lyrics, and cultural context through deep music understanding. Supports audio up to 20 minutes (MP3, WAV, FLAC). Two modes: (1) **Presets** — pass a `preset` name like `catalog_metadata`, `mood_tags`, or `full_report` for structured, optimized output. (2) **Custom prompt** — pass a `prompt` for free-form questions. The `full_report` preset runs all 13 presets in parallel and returns a comprehensive music intelligence report. Use `GET /api/songs/analyze/presets` to list available presets.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Music analysis request", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SongAnalyzeRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Music analysis completed successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SongAnalyzeResponse" - } - } - } - }, - "400": { - "description": "Bad request — missing or invalid fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SongAnalyzeErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key / Bearer token", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SongAnalyzeErrorResponse" - } - } - } - }, - "500": { - "description": "Server error — upstream model unavailable or inference failed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SongAnalyzeErrorResponse" - } - } - } - } - } - } - }, - "/api/notifications": { - "post": { - "description": "Send a notification email to the authenticated account's email address via the Resend API. Emails are sent from `Agent by Recoup `. The recipient is automatically resolved from the API key or Bearer token. Supports plain text (rendered as Markdown) or raw HTML bodies, optional CC recipients, custom headers, and an optional room_id to include a chat link in the email footer.", - "requestBody": { - "description": "Notification email payload", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateNotificationRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Notification sent successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotificationResponse" - } - } - } - }, - "400": { - "description": "Validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "401": { - "description": "Authentication required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "502": { - "description": "Email delivery failed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - } - }, - "/api/admins": { - "get": { - "description": "Check if the authenticated account is a Recoup admin. An account is considered an admin if it is a member of the Recoup organization. No input parameters required — authentication is performed via the x-api-key or Authorization header.", - "parameters": [], - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "responses": { - "200": { - "description": "Admin status retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CheckAdminResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - } - } - } - }, - "/api/admins/sandboxes": { - "get": { - "description": "Returns a list of all accounts and their sandbox usage statistics. Each item includes the account email, total number of sandboxes created, and the timestamp of the most recently created sandbox. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.", - "parameters": [], - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "responses": { - "200": { - "description": "Account sandbox statistics retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AdminSandboxesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - authenticated account is not a Recoup admin", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - } - } - } - }, - "/api/admins/sandboxes/orgs": { - "get": { - "description": "Returns commit statistics for each repository in the recoupable GitHub organization. Each item includes the repo name, URL, total commit count, latest 5 commit messages, earliest and latest commit timestamps, and the list of account repo URLs that include this org repo as a submodule. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.", - "parameters": [], - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "responses": { - "200": { - "description": "Org repo statistics retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AdminSandboxOrgsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - authenticated account is not a Recoup admin", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - } - } - } - }, - "/api/admins/emails": { - "get": { - "description": "Returns Resend emails including HTML content. Provide either account_id (returns all emails for an account) or email_id (returns a single email by Resend ID). Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token. Email response shape matches the [Resend Retrieve Email API](https://resend.com/docs/api-reference/emails/retrieve-email).", - "parameters": [ - { - "name": "account_id", - "in": "query", - "description": "The account ID to fetch all emails for. Required if email_id is not provided.", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "email_id", - "in": "query", - "description": "A Resend email ID to fetch a single email. Required if account_id is not provided.", - "required": false, - "schema": { - "type": "string" - } - } - ], - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "responses": { - "200": { - "description": "Emails retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AdminEmailsResponse" - } - } - } - }, - "400": { - "description": "Bad request - must provide either account_id or email_id", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "401": { - "description": "Unauthorized - missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - authenticated account is not a Recoup admin", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - } - } - } - }, - "/api/admins/coding/slack": { - "get": { - "description": "Returns a list of Slack mentions of the Recoup Coding Agent bot, pulled directly from the Slack API as the source of truth. Each entry includes the tagger's information, the prompt they sent, the timestamp, the channel, and any GitHub pull request URLs opened in response. Also returns aggregate pull request statistics. Supports optional time-period filtering. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.", - "parameters": [ - { - "name": "period", - "in": "query", - "description": "Time period to filter tags. One of: all (no date filter), daily (last 24 hours), weekly (last 7 days), monthly (last 30 days). Defaults to all.", - "required": false, - "schema": { - "type": "string", - "enum": [ - "all", - "daily", - "weekly", - "monthly" - ], - "default": "all" - } - } - ], - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "responses": { - "200": { - "description": "Slack tag analytics retrieved successfully", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "status", - "total", - "total_pull_requests", - "tags_with_pull_requests", - "tags" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "total": { - "type": "integer", - "description": "Total number of times the Coding Agent was tagged in the requested period", - "example": 134 - }, - "total_pull_requests": { - "type": "integer", - "description": "Total number of pull requests opened by the Coding Agent across all tags in the requested period", - "example": 121 - }, - "tags_with_pull_requests": { - "type": "integer", - "description": "Number of tags that resulted in at least one pull request being opened", - "example": 84 - }, - "tags": { - "type": "array", - "description": "List of Slack tag events", - "items": { - "type": "object", - "required": [ - "user_id", - "user_name", - "prompt", - "timestamp", - "channel_id", - "channel_name" - ], - "properties": { - "user_id": { - "type": "string", - "description": "Slack ID of the person who tagged the agent", - "example": "U012AB3CD" - }, - "user_name": { - "type": "string", - "description": "Display name of the person who tagged the agent", - "example": "Jane Smith" - }, - "user_avatar": { - "type": [ - "string", - "null" - ], - "description": "URL of the Slack avatar", - "example": "https://avatars.slack-edge.com/..." - }, - "prompt": { - "type": "string", - "description": "The text of the message sent to the agent", - "example": "add dark mode support to the settings page" - }, - "timestamp": { - "type": "string", - "format": "date-time", - "description": "ISO 8601 timestamp of the tag event", - "example": "2024-01-15T10:30:00.000Z" - }, - "channel_id": { - "type": "string", - "description": "Slack channel ID where the tag occurred", - "example": "C012AB3CD" - }, - "channel_name": { - "type": "string", - "description": "Human-readable name of the Slack channel", - "example": "dev-team" - }, - "pull_requests": { - "type": "array", - "description": "GitHub pull request URLs opened by the Coding Agent in response to this prompt, parsed from bot replies in the Slack thread", - "items": { - "type": "string", - "format": "uri", - "example": "https://github.com/recoupable/api/pull/42" - }, - "example": [ - "https://github.com/recoupable/api/pull/42" - ] - } - } - } - } - } - } - } - } - }, - "401": { - "description": "Unauthorized - missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - authenticated account is not a Recoup admin", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - } - } - } - }, - "/api/admins/content/slack": { - "get": { - "description": "Returns a list of Slack mentions of the Recoup Content Agent bot, pulled directly from the Slack API as the source of truth. Each entry includes the tagger's information, the prompt they sent, the timestamp, the channel, and any video link responses. Also returns aggregate video statistics for measuring tag-to-video conversion. Supports optional time-period filtering. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.", - "parameters": [ - { - "name": "period", - "in": "query", - "description": "Time period to filter tags. One of: all (no date filter), daily (last 24 hours), weekly (last 7 days), monthly (last 30 days). Defaults to all.", - "required": false, - "schema": { - "type": "string", - "enum": [ - "all", - "daily", - "weekly", - "monthly" - ], - "default": "all" - } - } - ], - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "responses": { - "200": { - "description": "Slack tag analytics retrieved successfully", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "status", - "total", - "total_videos", - "tags_with_videos", - "tags" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "total": { - "type": "integer", - "description": "Total number of times the Content Agent was tagged in the requested period", - "example": 18 - }, - "total_videos": { - "type": "integer", - "description": "Total number of videos generated by the Content Agent across all tags in the requested period", - "example": 12 - }, - "tags_with_videos": { - "type": "integer", - "description": "Number of tags that resulted in at least one video being generated", - "example": 10 - }, - "tags": { - "type": "array", - "description": "List of Slack tag events", - "items": { - "type": "object", - "required": [ - "user_id", - "user_name", - "prompt", - "timestamp", - "channel_id", - "channel_name" - ], - "properties": { - "user_id": { - "type": "string", - "description": "Slack ID of the person who tagged the agent", - "example": "U012AB3CD" - }, - "user_name": { - "type": "string", - "description": "Display name of the person who tagged the agent", - "example": "Jane Smith" - }, - "user_avatar": { - "type": [ - "string", - "null" - ], - "description": "URL of the Slack avatar", - "example": "https://avatars.slack-edge.com/..." - }, - "prompt": { - "type": "string", - "description": "The text of the message sent to the agent", - "example": "create a highlight reel for the new single release" - }, - "timestamp": { - "type": "string", - "format": "date-time", - "description": "ISO 8601 timestamp of the tag event", - "example": "2024-01-15T10:30:00.000Z" - }, - "channel_id": { - "type": "string", - "description": "Slack channel ID where the tag occurred", - "example": "C012AB3CD" - }, - "channel_name": { - "type": "string", - "description": "Human-readable name of the Slack channel", - "example": "content-team" - }, - "video_links": { - "type": "array", - "description": "Video URLs generated by the Content Agent in response to this prompt, parsed from bot replies in the Slack thread", - "items": { - "type": "string", - "format": "uri", - "example": "https://recoupable.com/v/abc123" - }, - "example": [ - "https://recoupable.com/v/abc123" - ] - } - } - } - } - } - } - } - } - }, - "401": { - "description": "Unauthorized - missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - authenticated account is not a Recoup admin", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - } - } - } - }, - "/api/admins/coding/pr": { - "get": { - "description": "Returns the status (open, closed, or merged) for each provided GitHub pull request URL. Accepts one or more `pull_requests` query parameters containing GitHub PR URLs. Uses the GitHub REST API to check each pull request's state. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.", - "parameters": [ - { - "name": "pull_requests", - "in": "query", - "description": "One or more GitHub pull request URLs to check. Repeat this parameter for each URL. Example: ?pull_requests=https://github.com/org/repo/pull/1&pull_requests=https://github.com/org/repo/pull/2", - "required": true, - "schema": { - "type": "array", - "items": { - "type": "string", - "format": "uri" - }, - "minItems": 1, - "maxItems": 50 - }, - "style": "form", - "explode": true - } - ], - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "responses": { - "200": { - "description": "PR merged status retrieved successfully", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "status", - "pull_requests" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "pull_requests": { - "type": "array", - "description": "Status for each provided pull request URL", - "items": { - "type": "object", - "required": [ - "url", - "status" - ], - "properties": { - "url": { - "type": "string", - "format": "uri", - "description": "The GitHub pull request URL", - "example": "https://github.com/recoupable/api/pull/42" - }, - "status": { - "type": "string", - "enum": [ - "open", - "closed", - "merged" - ], - "description": "The current status of the pull request", - "example": "merged" - } - } - } - } - } - } - } - } - }, - "400": { - "description": "Bad request - missing or invalid pull_requests parameter", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized - missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - authenticated account is not a Recoup admin", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - } - } - } - }, - "/api/admins/privy": { - "get": { - "description": "Returns Privy login statistics for a given time period. Results include counts for new accounts (created_at), active accounts (latest_verified_at), total Privy accounts across all time, and the full, unmodified Privy account objects. See [Privy User object documentation](https://docs.privy.io/api-reference/users/get-all) for the complete type definition. Defaults to period=all (no date filter). Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.", - "parameters": [ - { - "name": "period", - "in": "query", - "description": "Time period to filter logins. One of: all (no date filter), daily (last 24 hours), weekly (last 7 days), monthly (last 30 days). Defaults to all.", - "required": false, - "schema": { - "type": "string", - "enum": [ - "all", - "daily", - "weekly", - "monthly" - ], - "default": "all" - } - } - ], - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "responses": { - "200": { - "description": "Privy login statistics retrieved successfully", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "status", - "total", - "total_new", - "total_active", - "logins" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "total": { - "type": "integer", - "description": "Total number of accounts in Privy across all time (not filtered by period)", - "example": 42 - }, - "total_new": { - "type": "integer", - "description": "Number of accounts created (created_at) within the requested period", - "example": 15 - }, - "total_active": { - "type": "integer", - "description": "Total number of accounts matching either new or active criteria in the requested period", - "example": 30 - }, - "logins": { - "type": "array", - "description": "Full, unmodified Privy account objects. See [Privy User object docs](https://docs.privy.io/api-reference/users/get-all) for the complete type definition.", - "items": { - "type": "object" - } - } - } - } - } - } - }, - "401": { - "description": "Unauthorized - missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden - authenticated account is not a Recoup admin", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountErrorResponse" - } - } - } - } - } - } - }, - "/api/content-agent/{platform}": { - "post": { - "description": "Webhook endpoint for the Recoup Content Agent Slack bot. Receives @mention events from Slack and triggers content generation for the mentioned artist. The bot parses the mention text for ` [template] [batch=N] [lipsync]`, validates the artist, calls POST /api/content/create, and starts a background polling task that reports results back to the Slack thread.\n\nFor Slack, also handles `url_verification` challenges during app setup.", - "parameters": [ - { - "name": "platform", - "in": "path", - "description": "Chat platform identifier. Currently supports `slack`.", - "required": true, - "schema": { - "type": "string", - "enum": [ - "slack" - ] - } - } - ], - "requestBody": { - "description": "Slack Events API payload (app_mention event or url_verification challenge)", - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "description": "Slack Events API envelope — the shape depends on the event type" - } - } - } - }, - "responses": { - "200": { - "description": "Event processed successfully", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "ok": { - "type": "boolean" - } - } - } - } - } - }, - "404": { - "description": "Unknown platform" - } - } - } - }, - "/api/content-agent/callback": { - "post": { - "description": "Internal callback endpoint for the `poll-content-run` Trigger.dev task. Receives content generation results and posts them back to the originating Slack thread. Authenticated via the `x-callback-secret` header.\n\nThis endpoint is not intended for external use — it is called automatically by the polling task when content runs complete, fail, or time out.", - "requestBody": { - "description": "Content generation results from the polling task", - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "threadId", - "status" - ], - "properties": { - "threadId": { - "type": "string", - "description": "Chat SDK thread identifier for the originating Slack thread" - }, - "status": { - "type": "string", - "enum": [ - "completed", - "failed", - "timeout" - ], - "description": "Overall status of the content generation batch" - }, - "results": { - "type": "array", - "description": "Per-run results", - "items": { - "type": "object", - "required": [ - "runId", - "status" - ], - "properties": { - "runId": { - "type": "string", - "description": "Trigger.dev run ID" - }, - "status": { - "type": "string", - "enum": [ - "completed", - "failed", - "timeout" - ] - }, - "videoUrl": { - "type": "string", - "description": "URL of the generated video (when completed)" - }, - "captionText": { - "type": "string", - "description": "Generated caption text (when completed)" - }, - "error": { - "type": "string", - "description": "Error message (when failed)" - } - } - } - }, - "message": { - "type": "string", - "description": "Optional human-readable message" - } - } - } - } - } - }, - "responses": { - "200": { - "description": "Callback processed and results posted to Slack", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "status": { - "type": "string", - "example": "ok" - } - } - } - } - } - }, - "400": { - "description": "Invalid request body" - }, - "401": { - "description": "Missing or invalid callback secret" - } - }, - "security": [ - { - "callbackSecret": [] - } - ] - } - }, - "/api/content/upscale": { - "post": { - "description": "Upscale an image or video to higher resolution. Pass the URL and specify the type. Returns the upscaled URL.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Upscale parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateUpscaleRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Media upscaled successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateUpscaleResponse" - } - } - } - }, - "400": { - "description": "Validation failed — invalid or missing request body fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - } - } - } - }, - "/api/content/analyze": { - "post": { - "description": "Analyze a video and answer questions about it. Pass a video URL and a text prompt — for example, \"Describe what happens\" or \"Rate the visual quality 1-10.\" Returns the generated text.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Video analysis parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateAnalyzeRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Video analyzed successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateAnalyzeResponse" - } - } - } - }, - "400": { - "description": "Validation failed — invalid or missing request body fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "502": { - "description": "Video analysis failed upstream", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - } - } - } - }, - "/api/content/caption": { - "post": { - "description": "Generate a short caption from a topic. Returns the text content and default styling (font, color, size).", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Text generation parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateTextRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Text generated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateTextResponse" - } - } - } - }, - "400": { - "description": "Validation failed — invalid or missing request body fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - } - } - } - }, - "/api/content/image": { - "post": { - "description": "Generate an image from a text prompt. Pass a `reference_image_url` to guide the output toward a specific look or subject. Returns the image URL.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Image generation parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateImageRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Image generated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateImageResponse" - } - } - } - }, - "400": { - "description": "Validation failed — invalid or missing request body fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - } - } - } - }, - "/api/content/video": { - "post": { - "description": "Generate a video. Set `mode` to control what kind of video you get:\n\n- `prompt` — create a video from a text description\n- `animate` — animate a still image\n- `reference` — use an image as a style/subject reference (not the first frame)\n- `extend` — continue an existing video\n- `first-last` — generate a video that transitions between two images\n- `lipsync` — sync face movement to an audio clip\n\nIf `mode` is omitted, it's inferred from the inputs you provide.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Video generation parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateVideoRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Video generated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateVideoResponse" - } - } - } - }, - "400": { - "description": "Validation failed — invalid or missing request body fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - } - } - } - }, - "/api/content/transcribe": { - "post": { - "description": "Transcribe audio into text with word-level timestamps. Pass one or more audio file URLs in `audio_urls`. Returns the full transcript and an array of timed segments.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Audio transcription parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateAudioRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Song transcribed successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentCreateAudioResponse" - } - } - } - }, - "400": { - "description": "Validation failed — invalid or missing request body fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContentErrorResponse" - } - } - } - } - } - } - }, - "/api/music/compose": { - "post": { - "description": "Generate a song from a text prompt or a composition plan. The prompt can describe mood, genre, instruments, lyrics, and structure. Alternatively, pass a full composition_plan for fine-grained control over sections, styles, and lyrics. Returns binary audio in the requested format (default MP3).", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Music composition parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicComposeRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Audio generated successfully", - "headers": { - "song-id": { - "schema": { - "type": "string" - }, - "description": "Unique identifier for the generated song" - } - }, - "content": { - "audio/mpeg": { - "schema": { - "type": "string", - "format": "binary" - } - } - } - }, - "400": { - "description": "Validation failed — invalid or missing request body fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - } - } - } - }, - "/api/music/compose/detailed": { - "post": { - "description": "Generate a song with metadata and optional word-level timestamps. Returns a multipart/mixed response: the first part is JSON metadata (song ID, duration, seed, etc.) and the second part is binary audio. Use with_timestamps to get precise timing for each word in the lyrics.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Music composition parameters with optional timestamps", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicComposeDetailedRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Audio and metadata generated successfully. Response is multipart/mixed: JSON metadata followed by binary audio.", - "content": { - "multipart/mixed": { - "schema": { - "type": "string", - "format": "binary" - } - } - } - }, - "400": { - "description": "Validation failed — invalid or missing request body fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - } - } - } - }, - "/api/music/stream": { - "post": { - "description": "Generate a song and stream audio chunks in real time. Use this endpoint when you want to begin playback before the full song is generated. The response streams binary audio chunks as they are produced.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Music streaming parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicStreamRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Audio stream started successfully", - "headers": { - "song-id": { - "schema": { - "type": "string" - }, - "description": "Unique identifier for the generated song" - } - }, - "content": { - "audio/mpeg": { - "schema": { - "type": "string", - "format": "binary" - } - } - } - }, - "400": { - "description": "Validation failed — invalid or missing request body fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - } - } - } - }, - "/api/music/plan": { - "post": { - "description": "Create a composition plan from a text prompt. A composition plan is a structured representation of a song — sections, styles, lyrics, and durations — that you can review and tweak before passing to the compose endpoint. This endpoint is free and does not consume credits.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Plan creation parameters", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicCreatePlanRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Composition plan created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicCreatePlanResponse" - } - } - } - }, - "400": { - "description": "Validation failed — invalid or missing request body fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - } - } - } - }, - "/api/music/video-to-music": { - "post": { - "description": "Generate background music from video files. Upload 1–10 video files via multipart/form-data (max 200 MB total). The AI analyzes the video content and generates music that matches the mood, pacing, and style. Optionally provide a text description and style tags to guide the output.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Video files and optional generation parameters", - "required": true, - "content": { - "multipart/form-data": { - "schema": { - "type": "object", - "properties": { - "files": { - "type": "array", - "items": { - "type": "string", - "format": "binary" - }, - "minItems": 1, - "maxItems": 10, - "description": "Video files to analyze (max 200 MB total)" - }, - "description": { - "type": "string", - "maxLength": 1000, - "description": "Optional text description to guide the music generation" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "maxItems": 10, - "description": "Optional style tags to influence the output (max 10)" - }, - "sign_with_c2pa": { - "type": "boolean", - "default": false, - "description": "Sign the output with C2PA content credentials" - }, - "output_format": { - "type": "string", - "description": "Audio output format (e.g. mp3_44100_192)" - } - }, - "required": [ - "files" - ] - } - } - } - }, - "responses": { - "200": { - "description": "Background music generated successfully", - "headers": { - "song-id": { - "schema": { - "type": "string" - }, - "description": "Unique identifier for the generated song" - } - }, - "content": { - "audio/mpeg": { - "schema": { - "type": "string", - "format": "binary" - } - } - } - }, - "400": { - "description": "Validation failed — invalid or missing request body fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - } - } - } - }, - "/api/music/stem-separation": { - "post": { - "description": "Separate an audio file into individual stems (vocals, drums, bass, etc.). Upload an audio file via multipart/form-data. Choose between two-stem separation (vocals + instrumental) or six-stem separation (vocals, drums, bass, guitar, piano, other). Returns a ZIP archive containing the separated stems.", - "security": [ - { - "apiKeyAuth": [] - }, - { - "bearerAuth": [] - } - ], - "requestBody": { - "description": "Audio file and separation parameters", - "required": true, - "content": { - "multipart/form-data": { - "schema": { - "type": "object", - "properties": { - "file": { - "type": "string", - "format": "binary", - "description": "Audio file to separate into stems" - }, - "stem_variation_id": { - "type": "string", - "enum": [ - "two_stems_v1", - "six_stems_v1" - ], - "default": "six_stems_v1", - "description": "Stem separation mode. `two_stems_v1` produces vocals + instrumental. `six_stems_v1` produces vocals, drums, bass, guitar, piano, and other." - }, - "sign_with_c2pa": { - "type": "boolean", - "default": false, - "description": "Sign the output with C2PA content credentials" - }, - "output_format": { - "type": "string", - "description": "Audio output format (e.g. mp3_44100_192)" - } - }, - "required": [ - "file" - ] - } - } - } - }, - "responses": { - "200": { - "description": "Stems separated successfully. Returns a ZIP archive containing the individual stems.", - "content": { - "application/zip": { - "schema": { - "type": "string", - "format": "binary" - } - } - } - }, - "400": { - "description": "Validation failed — invalid or missing request body fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — invalid or missing API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MusicErrorResponse" - } - } - } - } - } - } - }, - "/api/research": { - "get": { - "description": "Search for artists by name. Returns matching results with profile summaries.", - "parameters": [ - { - "name": "q", - "in": "query", - "required": true, - "description": "Artist name to search for.", - "schema": { - "type": "string" - } - }, - { - "name": "type", - "in": "query", - "required": false, - "description": "Entity type.", - "schema": { - "type": "string", - "enum": [ - "artists", - "tracks", - "albums", - "playlists", - "curators", - "stations" - ], - "default": "artists" - } - }, - { - "name": "limit", - "in": "query", - "required": false, - "description": "Maximum number of results.", - "schema": { - "type": "integer", - "default": 10 - } - } - ], - "responses": { - "200": { - "description": "Search results", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchSearchResponse" - } - } - } - } - } - } - }, - "/api/research/albums": { - "get": { - "description": "Get an artist's full discography — albums, EPs, and singles with release dates.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID (UUID).", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Artist albums", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchAlbumsResponse" - } - } - } - } - } - } - }, - "/api/research/audience": { - "get": { - "description": "Get audience demographics for an artist on a specific platform — age, gender, and country breakdown.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID (UUID).", - "schema": { - "type": "string" - } - }, - { - "name": "platform", - "in": "query", - "required": false, - "description": "Platform to get demographics for. Defaults to instagram.", - "schema": { - "type": "string", - "enum": [ - "instagram", - "tiktok", - "youtube" - ], - "default": "instagram" - } - } - ], - "responses": { - "200": { - "description": "Audience demographics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchAudienceResponse" - } - } - } - } - } - } - }, - "/api/research/career": { - "get": { - "description": "Get an artist's career timeline — key milestones, trajectory, and career stage.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID (UUID).", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Career timeline", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchCareerResponse" - } - } - } - } - } - } - }, - "/api/research/charts": { - "get": { - "description": "Get global chart positions for a platform — Spotify, Apple Music, TikTok, YouTube, iTunes, Shazam, etc. NOT artist-scoped. Returns ranked entries with track and artist info.", - "parameters": [ - { - "name": "platform", - "in": "query", - "required": true, - "description": "Chart platform: spotify, applemusic, tiktok, youtube, itunes, shazam, etc.", - "schema": { - "type": "string" - } - }, - { - "name": "country", - "in": "query", - "required": false, - "description": "Two-letter country code (e.g. US, GB, DE).", - "schema": { - "type": "string" - } - }, - { - "name": "interval", - "in": "query", - "required": false, - "description": "Time interval (e.g. daily, weekly).", - "schema": { - "type": "string" - } - }, - { - "name": "type", - "in": "query", - "required": false, - "description": "Chart type (varies by platform).", - "schema": { - "type": "string" - } - }, - { - "name": "latest", - "in": "query", - "required": false, - "description": "Return only the latest chart.", - "schema": { - "type": "string", - "default": "true" - } - } - ], - "responses": { - "200": { - "description": "Chart data", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchChartsResponse" - } - } - } - } - } - } - }, - "/api/research/cities": { - "get": { - "description": "Get the top cities where an artist's fans listen, ranked by listener concentration.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID (UUID).", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Top listener cities", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchCitiesResponse" - } - } - } - } - } - } - }, - "/api/research/curator": { - "get": { - "description": "Get curator profile — who curates a playlist, their other playlists, and follower reach.", - "parameters": [ - { - "name": "platform", - "in": "query", - "required": true, - "schema": { - "type": "string", - "enum": [ - "spotify", - "applemusic", - "deezer", - "amazon", - "youtube" - ] - }, - "description": "Streaming platform." - }, - { - "name": "id", - "in": "query", - "required": true, - "description": "Curator ID.", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Curator profile", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchCuratorResponse" - } - } - } - } - } - } - }, - "/api/research/deep": { - "post": { - "description": "Perform deep, comprehensive research on a topic. Browses multiple sources extensively and returns a cited report. Use for full artist deep dives, competitive analysis, and any research requiring synthesis across many sources.", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchDeepRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Deep research report with citations", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchDeepResponse" - } - } - } - } - } - } - }, - "/api/research/discover": { - "get": { - "description": "Discover artists by criteria — filter by country, genre, Spotify monthly listener range, and sort by growth metrics.", - "parameters": [ - { - "name": "country", - "in": "query", - "required": false, - "description": "ISO country code (e.g., US, BR, GB).", - "schema": { - "type": "string" - } - }, - { - "name": "genre", - "in": "query", - "required": false, - "description": "Genre ID (use GET /api/research/genres to list).", - "schema": { - "type": "integer" - } - }, - { - "name": "sp_monthly_listeners_min", - "in": "query", - "required": false, - "schema": { - "type": "integer" - } - }, - { - "name": "sp_monthly_listeners_max", - "in": "query", - "required": false, - "schema": { - "type": "integer" - } - }, - { - "name": "sort", - "in": "query", - "required": false, - "description": "Sort field (e.g., weekly_diff.sp_monthly_listeners).", - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "default": 20 - } - } - ], - "responses": { - "200": { - "description": "Filtered artist list", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchDiscoverResponse" - } - } - } - } - } - } - }, - "/api/research/enrich": { - "post": { - "description": "Enrich an entity with structured data from web research. Provide a description of who or what to research and a JSON schema defining the fields to extract. Returns typed data with citations.", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchEnrichRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Structured enrichment data", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchEnrichResponse" - } - } - } - } - } - } - }, - "/api/research/extract": { - "post": { - "description": "Extract clean markdown content from one or more public URLs. Handles JavaScript-heavy pages and PDFs. Returns focused excerpts aligned to an objective, or full page content.", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchExtractRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Extracted content from URLs", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchExtractResponse" - } - } - } - } - } - } - }, - "/api/research/festivals": { - "get": { - "description": "List music festivals.", - "responses": { - "200": { - "description": "Festival list", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchFestivalsResponse" - } - } - } - } - } - } - }, - "/api/research/genres": { - "get": { - "description": "List all available genre IDs and names. Use these IDs with the discover endpoint at GET /api/research/discover.", - "responses": { - "200": { - "description": "Genre list", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchGenresResponse" - } - } - } - } - } - } - }, - "/api/research/insights": { - "get": { - "description": "Get AI-generated insights about an artist — automatically surfaced trends, milestones, and observations.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID (UUID).", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "AI-generated insights", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchInsightsResponse" - } - } - } - } - } - } - }, - "/api/research/instagram-posts": { - "get": { - "description": "Get an artist's top Instagram posts and reels, sorted by engagement.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID (UUID).", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Top Instagram posts and reels", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchInstagramPostsResponse" - } - } - } - } - } - } - }, - "/api/research/lookup": { - "get": { - "description": "Look up an artist by a platform URL or ID — Spotify URL, Spotify ID, Apple Music URL, etc.", - "parameters": [ - { - "name": "url", - "in": "query", - "required": true, - "description": "Platform URL or ID (e.g., Spotify artist URL, Spotify ID).", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Artist profile matching the platform URL", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchLookupResponse" - } - } - } - } - } - } - }, - "/api/research/metrics": { - "get": { - "description": "Get platform-specific metrics for an artist over time — followers, listeners, views, engagement. Supports 14 platforms.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID (UUID).", - "schema": { - "type": "string" - } - }, - { - "name": "source", - "in": "query", - "required": true, - "description": "Platform to get metrics for.", - "schema": { - "type": "string", - "enum": [ - "spotify", - "instagram", - "tiktok", - "twitter", - "facebook", - "youtube_channel", - "youtube_artist", - "soundcloud", - "deezer", - "twitch", - "line", - "melon", - "wikipedia", - "bandsintown" - ] - } - } - ], - "responses": { - "200": { - "description": "Platform metrics over time", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchMetricsResponse" - } - } - } - } - } - } - }, - "/api/research/milestones": { - "get": { - "description": "Get an artist's activity feed — playlist adds, chart entries, and other notable events. Each milestone includes a date, summary, platform, track name, and star rating.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID.", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Milestone list", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchMilestonesResponse" - } - } - } - } - } - } - }, - "/api/research/people": { - "post": { - "description": "Search for people in the music industry — artists, managers, A&R reps, producers. Returns multi-source profiles including LinkedIn data.", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchPeopleRequest" - } - } - } - }, - "responses": { - "200": { - "description": "People search results", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchPeopleResponse" - } - } - } - } - } - } - }, - "/api/research/playlist": { - "get": { - "description": "Get playlist metadata — name, description, follower count, track count, and curator info.", - "parameters": [ - { - "name": "platform", - "in": "query", - "required": true, - "schema": { - "type": "string", - "enum": [ - "spotify", - "applemusic", - "deezer", - "amazon", - "youtube" - ] - }, - "description": "Streaming platform." - }, - { - "name": "id", - "in": "query", - "required": true, - "description": "Playlist ID on the platform.", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Playlist metadata", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchPlaylistResponse" - } - } - } - } - } - } - }, - "/api/research/playlists": { - "get": { - "description": "Get an artist's playlist placements — editorial, algorithmic, and indie playlists across platforms.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID (UUID).", - "schema": { - "type": "string" - } - }, - { - "name": "platform", - "in": "query", - "required": false, - "schema": { - "type": "string", - "enum": [ - "spotify", - "applemusic", - "deezer", - "amazon", - "youtube" - ], - "default": "spotify" - } - }, - { - "name": "status", - "in": "query", - "required": false, - "schema": { - "type": "string", - "enum": [ - "current", - "past" - ], - "default": "current" - } - }, - { - "name": "editorial", - "in": "query", - "required": false, - "description": "Only editorial playlists.", - "schema": { - "type": "boolean" - } - }, - { - "name": "since", - "in": "query", - "required": false, - "description": "Filter by date (YYYY-MM-DD).", - "schema": { - "type": "string", - "format": "date" - } - }, - { - "name": "sort", - "in": "query", - "required": false, - "description": "Sort results by this field.", - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "default": 20 - } - } - ], - "responses": { - "200": { - "description": "Playlist placements", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchPlaylistsResponse" - } - } - } - } - } - } - }, - "/api/research/profile": { - "get": { - "description": "Get a full artist profile — bio, genres, social URLs, label, career stage, and basic metrics.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID (UUID).", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Artist profile", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchProfileResponse" - } - } - } - } - } - } - }, - "/api/research/radio": { - "get": { - "description": "List radio stations tracked by Chartmetric. NOT artist-scoped. Returns station names, formats, and markets.", - "responses": { - "200": { - "description": "Radio station list", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchRadioResponse" - } - } - } - } - } - } - }, - "/api/research/rank": { - "get": { - "description": "Get an artist's global Chartmetric ranking as a single integer value.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID.", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Artist rank", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchRankResponse" - } - } - } - } - } - } - }, - "/api/research/similar": { - "get": { - "description": "Find similar artists based on audience overlap, genre, mood, and musicality. Use for competitive analysis and collaboration discovery.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID (UUID).", - "schema": { - "type": "string" - } - }, - { - "name": "audience", - "in": "query", - "required": false, - "description": "Audience overlap weight.", - "schema": { - "type": "string", - "enum": [ - "high", - "medium", - "low" - ] - } - }, - { - "name": "genre", - "in": "query", - "required": false, - "description": "Genre similarity weight.", - "schema": { - "type": "string", - "enum": [ - "high", - "medium", - "low" - ] - } - }, - { - "name": "mood", - "in": "query", - "required": false, - "description": "Mood similarity weight.", - "schema": { - "type": "string", - "enum": [ - "high", - "medium", - "low" - ] - } - }, - { - "name": "musicality", - "in": "query", - "required": false, - "description": "Musicality similarity weight.", - "schema": { - "type": "string", - "enum": [ - "high", - "medium", - "low" - ] - } - }, - { - "name": "limit", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "default": 10 - } - } - ], - "responses": { - "200": { - "description": "Similar artists with overlap scores", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchSimilarResponse" - } - } - } - } - } - } - }, - "/api/research/track": { - "get": { - "description": "Get track metadata — title, artist, album, release date, popularity, and platform IDs.", - "parameters": [ - { - "name": "q", - "in": "query", - "required": true, - "description": "Track name or Spotify URL.", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Track metadata", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchTrackResponse" - } - } - } - } - } - } - }, - "/api/research/tracks": { - "get": { - "description": "Get all tracks by an artist with popularity data.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID (UUID).", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Artist tracks", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchTracksResponse" - } - } - } - } - } - } - }, - "/api/research/urls": { - "get": { - "description": "Get all social and streaming URLs for an artist — Spotify, Instagram, TikTok, YouTube, Twitter, SoundCloud, and more.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID (UUID).", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Social and streaming URLs", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchUrlsResponse" - } - } - } - } - } - } - }, - "/api/research/venues": { - "get": { - "description": "Get venues an artist has performed at, including capacity and location data.", - "parameters": [ - { - "name": "artist", - "in": "query", - "required": true, - "description": "Artist name or Recoup artist ID.", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Venue list", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchVenuesResponse" - } - } - } - } - } - } - }, - "/api/research/web": { - "post": { - "description": "Search the web for real-time information. Returns ranked results with titles, URLs, and content snippets. Use for narrative context, press coverage, and cultural research that structured data endpoints don't cover.", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchWebRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Web search results", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResearchWebResponse" - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "Error": { - "required": [ - "error", - "message" - ], - "type": "object", - "properties": { - "error": { - "type": "integer", - "format": "int32" - }, - "message": { - "type": "string" - } - } - }, - "CreateNotificationRequest": { - "type": "object", - "required": [ - "subject" - ], - "properties": { - "cc": { - "type": "array", - "items": { - "type": "string", - "format": "email" - }, - "description": "Optional CC email addresses", - "example": [ - "cc@example.com" - ] - }, - "subject": { - "type": "string", - "description": "Email subject line", - "example": "Weekly Pulse Report" - }, - "text": { - "type": "string", - "description": "Plain text or Markdown body. Rendered as HTML via Markdown if no `html` is provided.", - "example": "# Pulse Report\n\nHere's your weekly summary." - }, - "html": { - "type": "string", - "description": "Raw HTML body. Takes precedence over `text` when both are provided.", - "example": "

Pulse Report

Here's your weekly summary.

" - }, - "headers": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "description": "Optional custom email headers" - }, - "room_id": { - "type": "string", - "description": "Room ID to include a chat link in the email footer" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the account to send the notification for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, sends the notification for the API key's own account." - } - } - }, - "NotificationResponse": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Whether the notification was sent successfully", - "example": true - }, - "message": { - "type": "string", - "description": "Human-readable result message", - "example": "Email sent successfully from Agent by Recoup to user@example.com." - }, - "id": { - "type": "string", - "description": "Resend email ID", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - } - } - }, - "ConnectorInfo": { - "type": "object", - "required": [ - "slug", - "name", - "isConnected" - ], - "properties": { - "slug": { - "type": "string", - "description": "Unique identifier for the connector (e.g., 'googlesheets', 'tiktok')" - }, - "name": { - "type": "string", - "description": "Human-readable name of the connector" - }, - "isConnected": { - "type": "boolean", - "description": "Whether the connector is currently connected" - }, - "connectedAccountId": { - "type": "string", - "description": "The connected account ID (only present when isConnected is true)" - } - } - }, - "ConnectorsResponse": { - "type": "object", - "required": [ - "success", - "connectors" - ], - "properties": { - "success": { - "type": "boolean" - }, - "connectors": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ConnectorInfo" - }, - "description": "List of available connectors with connection status" - } - } - }, - "AuthorizeConnectorRequest": { - "type": "object", - "required": [ - "connector" - ], - "properties": { - "connector": { - "type": "string", - "description": "The connector slug to authorize (e.g., 'googlesheets', 'tiktok')" - }, - "callback_url": { - "type": "string", - "format": "uri", - "description": "Optional custom callback URL after OAuth completion" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "Optional account ID to connect a service for a different account (e.g., an artist, workspace, or organization). Use this when connecting an artist's TikTok or other service. The authenticated account must have access. Omit to connect for your own account." - } - } - }, - "AuthorizeConnectorResponse": { - "type": "object", - "required": [ - "success", - "data" - ], - "properties": { - "success": { - "type": "boolean" - }, - "data": { - "type": "object", - "required": [ - "connector", - "redirectUrl" - ], - "properties": { - "connector": { - "type": "string", - "description": "The connector slug being authorized" - }, - "redirectUrl": { - "type": "string", - "format": "uri", - "description": "URL to redirect to for OAuth authorization" - } - } - } - } - }, - "DisconnectConnectorRequest": { - "type": "object", - "required": [ - "connected_account_id" - ], - "properties": { - "connected_account_id": { - "type": "string", - "description": "The connected account ID to disconnect (from ConnectorInfo.connectedAccountId)" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "Optional account ID when disconnecting a connection that belongs to a different account (e.g., an artist). Required when the connection was created for another account rather than your own. The authenticated account must have access." - } - } - }, - "DisconnectConnectorResponse": { - "type": "object", - "required": [ - "success" - ], - "properties": { - "success": { - "type": "boolean" - }, - "message": { - "type": "string", - "description": "Status message" - } - } - }, - "CompactChatsRequest": { - "type": "object", - "required": [ - "chatId" - ], - "properties": { - "chatId": { - "type": "array", - "minItems": 1, - "items": { - "type": "string", - "format": "uuid" - }, - "description": "Array of chat IDs to compact" - }, - "prompt": { - "type": "string", - "description": "Optional prompt to control what information gets preserved in the compacted summary" - } - } - }, - "CompactChatsResponse": { - "type": "object", - "required": [ - "chats" - ], - "properties": { - "chats": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CompactedChat" - }, - "description": "Array of compacted chat results" - } - } - }, - "CompactedChat": { - "type": "object", - "required": [ - "chatId", - "compacted" - ], - "properties": { - "chatId": { - "type": "string", - "format": "uuid", - "description": "The ID of the chat that was compacted" - }, - "compacted": { - "type": "string", - "description": "The compacted summary text of the chat" - } - } - }, - "TasksResponse": { - "type": "object", - "required": [ - "status", - "tasks" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Status of the request" - }, - "tasks": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Task" - }, - "description": "Array of task objects" - }, - "error": { - "type": "string", - "description": "Error message (only present if status is error)" - } - } - }, - "Task": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "Unique identifier for the task" - }, - "title": { - "type": "string", - "description": "Descriptive title or name of the task" - }, - "prompt": { - "type": "string", - "description": "Detailed instruction or prompt for task execution" - }, - "schedule": { - "type": "string", - "description": "Cron expression defining when the task should execute (e.g., '0 10 * * *')" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "Unique identifier for the associated account" - }, - "artist_account_id": { - "type": "string", - "format": "uuid", - "description": "Unique identifier for the associated artist account" - }, - "enabled": { - "type": "boolean", - "nullable": true, - "description": "Whether the task is enabled. Defaults to true." - }, - "trigger_schedule_id": { - "type": "string", - "nullable": true, - "description": "Identifier for the trigger schedule associated with this task" - }, - "recent_runs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TaskRunResponse" - }, - "description": "Last 5 runs for this task, sourced from the Trigger.dev API." - }, - "upcoming": { - "type": "array", - "items": { - "type": "string", - "format": "date-time" - }, - "description": "Next scheduled run times, sourced from the latest Trigger.dev run payload." - } - } - }, - "CreateTaskRequest": { - "type": "object", - "required": [ - "title", - "prompt", - "schedule", - "account_id", - "artist_account_id" - ], - "properties": { - "title": { - "type": "string", - "description": "Descriptive title of the task", - "example": "Weekly Genre Pulse Check" - }, - "prompt": { - "type": "string", - "description": "Instruction/prompt executed by the task", - "example": "Execute this weekly genre analysis workflow and email a summary to the team." - }, - "schedule": { - "type": "string", - "description": "Cron expression defining when the task runs (e.g., '0 9 * * 4' for Thursdays at 9 AM)", - "example": "0 9 * * 4" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the associated account", - "example": "848cd58d-700f-4b38-ab4c-d9f52a1b2c3d" - }, - "artist_account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the associated artist account", - "example": "1873859c-dd37-4e9a-9bac-80d35a1b2c3d" - } - } - }, - "UpdateTaskRequest": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the task to update", - "example": "aade2bce-55c7-468e-a606-c4e76fb2ea2a" - }, - "title": { - "type": "string", - "description": "New descriptive title of the task", - "example": "Weekly Genre Pulse Check (Updated)" - }, - "prompt": { - "type": "string", - "description": "New instruction/prompt executed by the task", - "example": "Execute this weekly genre analysis workflow and email a summary to the team." - }, - "schedule": { - "type": "string", - "description": "New cron expression defining when the task runs", - "example": "0 10 * * 4" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "New UUID of the associated account", - "example": "848cd58d-700f-4b38-ab4c-d9f52a1b2c3d" - }, - "artist_account_id": { - "type": "string", - "format": "uuid", - "description": "New UUID of the associated artist account", - "example": "1873859c-dd37-4e9a-9bac-80d35a1b2c3d" - }, - "enabled": { - "type": "boolean", - "nullable": true, - "description": "Whether the task is enabled. Can be true, false, or null.", - "example": true - } - } - }, - "DeleteTaskRequest": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the task to delete", - "example": "aade2bce-55c7-468e-a606-c4e76fb2ea2a" - } - } - }, - "DeleteTaskResponse": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Status of the delete operation" - }, - "error": { - "type": "string", - "description": "Error message (only present if status is error)" - } - } - }, - "Account": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "Unique identifier for the account" - }, - "name": { - "type": "string", - "description": "Account display name" - }, - "image": { - "type": "string", - "nullable": true, - "description": "Profile image URL" - }, - "instruction": { - "type": "string", - "nullable": true, - "description": "Custom AI instructions for this account" - }, - "knowledges": { - "type": "array", - "nullable": true, - "items": { - "$ref": "#/components/schemas/Knowledge" - }, - "description": "Knowledge base files attached to this account" - }, - "email": { - "type": "string", - "nullable": true, - "description": "Primary email address" - }, - "wallet_address": { - "type": "string", - "nullable": true, - "description": "Connected wallet address" - } - } - }, - "Knowledge": { - "type": "object", - "properties": { - "url": { - "type": "string", - "description": "URL to the knowledge file" - }, - "name": { - "type": "string", - "description": "Name of the knowledge file" - }, - "type": { - "type": "string", - "description": "MIME type of the file" - } - } - }, - "GetAccountResponse": { - "type": "object", - "required": [ - "status", - "account" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "account": { - "$ref": "#/components/schemas/Account", - "description": "The account details" - } - } - }, - "GetAccountIdResponse": { - "type": "object", - "required": [ - "status", - "accountId" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "accountId": { - "type": "string", - "format": "uuid", - "description": "The unique identifier (UUID) of the authenticated account" - } - } - }, - "AccountErrorResponse": { - "type": "object", - "required": [ - "status", - "message" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "message": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "CreateAccountRequest": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "description": "Email address to associate with the account. If an account with this email exists, it will be returned." - }, - "wallet": { - "type": "string", - "description": "Wallet address to associate with the account. If an account with this wallet exists, it will be returned." - } - }, - "description": "At least one of email or wallet should be provided to identify or create an account." - }, - "UpdateAccountRequest": { - "type": "object", - "required": [ - "accountId" - ], - "properties": { - "accountId": { - "type": "string", - "format": "uuid", - "description": "The unique identifier of the account to update" - }, - "name": { - "type": "string", - "description": "Display name for the account" - }, - "instruction": { - "type": "string", - "description": "Custom instruction or bio for the account" - }, - "organization": { - "type": "string", - "description": "Organization name associated with the account" - }, - "image": { - "type": "string", - "format": "uri", - "description": "URL of the account's profile image" - }, - "jobTitle": { - "type": "string", - "description": "Job title of the account holder" - }, - "roleType": { - "type": "string", - "description": "Role type within the organization" - }, - "companyName": { - "type": "string", - "description": "Company name associated with the account" - }, - "knowledges": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Knowledge" - }, - "description": "Knowledge base files attached to this account" - } - } - }, - "AddArtistToAccountRequest": { - "type": "object", - "required": [ - "email", - "artistId" - ], - "properties": { - "email": { - "type": "string", - "format": "email", - "description": "Email address of the account to add the artist to" - }, - "artistId": { - "type": "string", - "format": "uuid", - "description": "The unique identifier of the artist to add" - } - } - }, - "AccountDataResponse": { - "type": "object", - "required": [ - "data" - ], - "properties": { - "data": { - "$ref": "#/components/schemas/AccountData", - "description": "The account data" - } - } - }, - "AccountData": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "The unique identifier of the account" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "The account ID (same as id, for consistency)" - }, - "name": { - "type": "string", - "description": "Display name of the account" - }, - "email": { - "type": "string", - "format": "email", - "description": "Email address associated with the account" - }, - "wallet": { - "type": "string", - "description": "Wallet address associated with the account" - }, - "image": { - "type": "string", - "format": "uri", - "description": "URL of the account's profile image" - }, - "instruction": { - "type": "string", - "description": "Custom instruction or bio" - }, - "organization": { - "type": "string", - "description": "Organization name" - }, - "job_title": { - "type": "string", - "description": "Job title" - }, - "role_type": { - "type": "string", - "description": "Role type" - }, - "company_name": { - "type": "string", - "description": "Company name" - }, - "knowledges": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Knowledge" - }, - "description": "Knowledge base files attached to this account" - } - } - }, - "AddArtistSuccessResponse": { - "type": "object", - "required": [ - "success" - ], - "properties": { - "success": { - "type": "boolean", - "enum": [ - true - ], - "description": "Indicates the artist was successfully added" - } - } - }, - "Artist": { - "type": "object", - "properties": { - "account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the artist account" - }, - "name": { - "type": "string", - "description": "Artist display name" - }, - "image": { - "type": "string", - "nullable": true, - "description": "Artist profile image URL" - }, - "pinned": { - "type": "boolean", - "description": "Whether the account has pinned this artist" - }, - "socials": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ArtistSocial" - }, - "description": "Social media profiles linked to the artist" - } - } - }, - "ArtistSocial": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the social profile" - }, - "platform": { - "type": "string", - "description": "Social media platform (e.g., instagram, twitter, tiktok)" - }, - "username": { - "type": "string", - "description": "Username on the platform" - }, - "profile_url": { - "type": "string", - "description": "Full URL to the social media profile" - } - } - }, - "ArtistsResponse": { - "type": "object", - "required": [ - "status", - "artists" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Status of the request" - }, - "artists": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Artist" - }, - "description": "List of artist objects" - }, - "message": { - "type": "string", - "description": "Error message (only present if status is error)" - } - } - }, - "ArtistsErrorResponse": { - "type": "object", - "required": [ - "status", - "message" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "message": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "CreateArtistRequest": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string", - "minLength": 1, - "description": "The name of the artist to create" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the account to create the artist for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, the artist is created for the API key's own account." - }, - "organization_id": { - "type": "string", - "format": "uuid", - "description": "Optional organization ID to link the new artist to" - } - } - }, - "CreateArtistResponse": { - "type": "object", - "required": [ - "artist" - ], - "properties": { - "artist": { - "$ref": "#/components/schemas/CreatedArtist" - } - } - }, - "CreatedArtist": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the created artist account" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the artist account (same as id)" - }, - "name": { - "type": "string", - "description": "Name of the artist" - }, - "created_at": { - "type": "string", - "format": "date-time", - "nullable": true, - "description": "ISO timestamp of when the artist was created" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "nullable": true, - "description": "ISO timestamp of when the artist was last updated" - }, - "image": { - "type": "string", - "nullable": true, - "description": "Artist profile image URL" - }, - "instruction": { - "type": "string", - "nullable": true, - "description": "Custom AI instruction for this artist" - }, - "knowledges": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "description": "Knowledge base references for this artist" - }, - "label": { - "type": "string", - "nullable": true, - "description": "Record label name" - }, - "organization": { - "type": "string", - "nullable": true, - "description": "Organization name" - }, - "company_name": { - "type": "string", - "nullable": true, - "description": "Company name" - }, - "job_title": { - "type": "string", - "nullable": true, - "description": "Job title" - }, - "role_type": { - "type": "string", - "nullable": true, - "description": "Role type" - }, - "onboarding_status": { - "type": "string", - "nullable": true, - "description": "Onboarding status" - }, - "onboarding_data": { - "nullable": true, - "description": "Onboarding data" - }, - "account_info": { - "type": "array", - "description": "Account info records" - }, - "account_socials": { - "type": "array", - "description": "Linked social media accounts" - } - } - }, - "CreateArtistError": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "missing_fields": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of missing or invalid field names" - }, - "error": { - "type": "string", - "description": "Error message describing the validation failure" - }, - "message": { - "type": "string", - "description": "Error message (for invalid JSON or other errors)" - } - } - }, - "ArtistSegment": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the artist_segments record" - }, - "artist_account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the artist's accounts record" - }, - "segment_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the segments record" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of when the segment data was last updated" - }, - "segment_name": { - "type": "string", - "description": "Name of the segment (e.g., 'Twitter Followers')" - }, - "artist_name": { - "type": "string", - "description": "Name of the artist" - } - } - }, - "ArtistSegmentsPagination": { - "type": "object", - "properties": { - "total_count": { - "type": "integer", - "description": "Total number of segments available" - }, - "page": { - "type": "integer", - "description": "Current page number" - }, - "limit": { - "type": "integer", - "description": "Number of segments per page" - }, - "total_pages": { - "type": "integer", - "description": "Total number of pages available" - } - } - }, - "ArtistSegmentsResponse": { - "type": "object", - "required": [ - "status", - "segments", - "pagination" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "segments": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ArtistSegment" - }, - "description": "List of segment objects associated with the artist" - }, - "pagination": { - "$ref": "#/components/schemas/ArtistSegmentsPagination", - "description": "Pagination metadata for the response" - } - } - }, - "ArtistSegmentsErrorResponse": { - "type": "object", - "required": [ - "status", - "message" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "message": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "SocialProfile": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the artist's account_socials record" - }, - "social_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the artist's socials account" - }, - "username": { - "type": "string", - "description": "Username on the platform" - }, - "profile_url": { - "type": "string", - "description": "Direct URL to the profile" - }, - "avatar": { - "type": "string", - "nullable": true, - "description": "URL to the profile avatar image" - }, - "bio": { - "type": "string", - "nullable": true, - "description": "Profile biography or description" - }, - "follower_count": { - "type": "integer", - "nullable": true, - "description": "Number of followers on this platform" - }, - "following_count": { - "type": "integer", - "nullable": true, - "description": "Number of accounts followed on this platform" - }, - "region": { - "type": "string", - "nullable": true, - "description": "Geographic region of the profile" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of when the profile was last updated" - } - } - }, - "ArtistSocialsPagination": { - "type": "object", - "properties": { - "total_count": { - "type": "integer", - "description": "Total number of social profiles available" - }, - "page": { - "type": "integer", - "description": "Current page number" - }, - "limit": { - "type": "integer", - "description": "Number of social profiles per page" - }, - "total_pages": { - "type": "integer", - "description": "Total number of pages available" - } - } - }, - "ArtistSocialsResponse": { - "type": "object", - "required": [ - "status", - "socials", - "pagination" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "socials": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SocialProfile" - }, - "description": "List of social media profiles associated with the artist" - }, - "pagination": { - "$ref": "#/components/schemas/ArtistSocialsPagination", - "description": "Pagination metadata for the response" - } - } - }, - "ArtistSocialsErrorResponse": { - "type": "object", - "required": [ - "status", - "message" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "message": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "ArtistSocialsScrapeRequest": { - "type": "object", - "required": [ - "artist_account_id" - ], - "properties": { - "artist_account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the artist account to scrape socials for", - "example": "1873859c-dd37-4e9a-9bac-80d35a1b2c3d" - } - } - }, - "ApifyRunResult": { - "type": "object", - "properties": { - "runId": { - "type": "string", - "description": "Unique identifier for the Apify run" - }, - "datasetId": { - "type": "string", - "description": "Unique identifier for the dataset containing scraped data" - }, - "error": { - "type": "string", - "nullable": true, - "description": "Error message if the run failed (null if successful)" - } - } - }, - "InstagramErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "message": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "ApifyScraperInProgressResponse": { - "type": "object", - "required": [ - "status", - "datasetId" - ], - "description": "Response when the Apify run is still in progress", - "properties": { - "status": { - "type": "string", - "description": "Current status of the Apify run (e.g., 'RUNNING', 'READY')", - "example": "RUNNING" - }, - "datasetId": { - "type": "string", - "description": "ID of the dataset that will contain the results when the run completes", - "example": "def456uvw" - } - } - }, - "ApifyScraperCompletedResponse": { - "type": "object", - "required": [ - "status", - "datasetId", - "data" - ], - "description": "Response when the Apify run has completed successfully", - "properties": { - "status": { - "type": "string", - "description": "Final status of the Apify run (typically 'SUCCEEDED')", - "example": "SUCCEEDED" - }, - "datasetId": { - "type": "string", - "description": "ID of the dataset containing the results", - "example": "def456uvw" - }, - "data": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": true - }, - "description": "Array of dataset items returned by the scraper. The structure of each item varies depending on the scraper type (Instagram Profile, Instagram Comments, etc.)", - "example": [ - { - "id": "123456789", - "username": "example_user", - "fullName": "Example User", - "biography": "This is a sample biography", - "followersCount": 1000, - "followsCount": 500, - "profilePicUrl": "https://example.com/profile.jpg" - } - ] - } - } - }, - "ApifyScraperErrorResponse": { - "type": "object", - "required": [ - "status", - "message" - ], - "description": "Error response from the Apify scraper results endpoint", - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status indicating an error occurred" - }, - "message": { - "type": "string", - "description": "Error message describing what went wrong", - "example": "runId is required" - } - } - }, - "ArtistSocialsScrapeResponse": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ApifyRunResult" - }, - "description": "Array of Apify run results, one for each social profile scraped" - }, - "ArtistProfileSocialProfile": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for the social profile" - }, - "username": { - "type": "string", - "description": "Username on the platform" - }, - "profile_url": { - "type": "string", - "description": "Direct URL to the profile" - }, - "avatar": { - "type": "string", - "nullable": true, - "description": "URL to the profile avatar image" - }, - "bio": { - "type": "string", - "nullable": true, - "description": "Profile biography or description" - }, - "follower_count": { - "type": "integer", - "nullable": true, - "description": "Number of followers on this platform" - }, - "following_count": { - "type": "integer", - "nullable": true, - "description": "Number of accounts followed on this platform" - }, - "post_count": { - "type": "integer", - "nullable": true, - "description": "Number of posts on this platform" - }, - "region": { - "type": "string", - "nullable": true, - "description": "Geographic region of the profile" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of when the profile was last updated" - } - } - }, - "ArtistProfile": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for the artist" - }, - "profiles": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ArtistProfileSocialProfile" - }, - "description": "List of social media profiles" - }, - "total_followers": { - "type": "integer", - "description": "Sum of followers across all platforms" - }, - "total_following": { - "type": "integer", - "description": "Sum of following across all platforms" - }, - "total_posts": { - "type": "integer", - "description": "Sum of posts across all platforms" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of when the data was last updated" - } - } - }, - "ArtistProfileResponse": { - "type": "object", - "required": [ - "status", - "profile" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "profile": { - "$ref": "#/components/schemas/ArtistProfile", - "description": "The artist's comprehensive profile information" - } - } - }, - "ArtistProfileErrorResponse": { - "type": "object", - "required": [ - "status", - "message" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "message": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "ChatRoom": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the chat room" - }, - "account_id": { - "type": "string", - "format": "uuid", - "nullable": true, - "description": "UUID of the associated account (can be null if not set)" - }, - "topic": { - "type": "string", - "nullable": true, - "description": "Optional topic or description of the room (null if not provided)" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of the last update to the room" - }, - "artist_id": { - "type": "string", - "format": "uuid", - "nullable": true, - "description": "UUID of the associated artist account (null when not applicable)" - } - } - }, - "GetChatsResponse": { - "type": "object", - "required": [ - "status", - "chats" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "chats": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChatRoom" - }, - "description": "Array of chat room objects" - } - } - }, - "GetChatsErrorResponse": { - "type": "object", - "required": [ - "status", - "error" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "GetChatArtistResponse": { - "type": "object", - "required": [ - "status", - "room_id", - "artist_id", - "artist_exists" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "room_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the chat room" - }, - "artist_id": { - "type": "string", - "format": "uuid", - "nullable": true, - "description": "UUID of the artist account associated with the chat, or null when no artist is linked" - }, - "artist_exists": { - "type": "boolean", - "description": "Whether an artist is linked to the chat room" - } - } - }, - "GetChatArtistErrorResponse": { - "type": "object", - "required": [ - "status", - "error" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "GetChatSegmentResponse": { - "type": "object", - "required": [ - "status", - "room_id", - "segment_id", - "segment_exists" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "room_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the chat room" - }, - "segment_id": { - "type": "string", - "format": "uuid", - "nullable": true, - "description": "UUID of the segment associated with the chat, or null when no segment is linked" - }, - "segment_exists": { - "type": "boolean", - "description": "Whether a segment is linked to the chat room" - } - } - }, - "GetChatSegmentErrorResponse": { - "type": "object", - "required": [ - "status", - "error" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "ChatMessage": { - "type": "object", - "required": [ - "id", - "room_id", - "content", - "updated_at" - ], - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the memory message" - }, - "room_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the parent chat room" - }, - "content": { - "type": "object", - "description": "Structured message payload stored for the memory" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of the memory update" - } - } - }, - "GetChatMessagesResponse": { - "type": "object", - "required": [ - "data" - ], - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChatMessage" - }, - "description": "Chronologically ordered list of messages for the chat" - } - } - }, - "GetChatMessagesErrorResponse": { - "type": "object", - "required": [ - "status", - "error" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "CopyChatMessagesRequest": { - "type": "object", - "required": [ - "targetChatId" - ], - "properties": { - "targetChatId": { - "type": "string", - "format": "uuid", - "description": "Target chat room UUID to receive the copied messages." - }, - "clearExisting": { - "type": "boolean", - "default": true, - "description": "When true, existing messages in the target chat are deleted before copy." - } - } - }, - "CopyChatMessagesResponse": { - "type": "object", - "required": [ - "status", - "source_chat_id", - "target_chat_id", - "copied_count", - "cleared_existing" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "source_chat_id": { - "type": "string", - "format": "uuid", - "description": "Source chat room UUID." - }, - "target_chat_id": { - "type": "string", - "format": "uuid", - "description": "Target chat room UUID." - }, - "copied_count": { - "type": "integer", - "description": "Number of messages copied from source to target." - }, - "cleared_existing": { - "type": "boolean", - "description": "Whether existing target messages were deleted before copy." - } - } - }, - "CopyChatMessagesErrorResponse": { - "type": "object", - "required": [ - "status", - "error" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong." - } - } - }, - "DeleteTrailingChatMessagesResponse": { - "type": "object", - "required": [ - "status", - "chat_id", - "from_message_id" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "chat_id": { - "type": "string", - "format": "uuid", - "description": "The chat UUID where deletion was applied." - }, - "from_message_id": { - "type": "string", - "format": "uuid", - "description": "The message UUID used as the trailing deletion boundary." - } - } - }, - "DeleteTrailingChatMessagesErrorResponse": { - "type": "object", - "required": [ - "status", - "error" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong." - }, - "missing_fields": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of missing or invalid parameter fields (when validation fails)." - } - } - }, - "CreateChatRequest": { - "type": "object", - "properties": { - "artistId": { - "type": "string", - "format": "uuid", - "description": "UUID of the artist account the chat is associated with" - }, - "chatId": { - "type": "string", - "format": "uuid", - "description": "UUID for the new chat (client-generated). If not provided, one will be generated automatically." - }, - "accountId": { - "type": "string", - "format": "uuid", - "description": "UUID of the account to create the chat for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, the chat is created for the API key's own account." - }, - "topic": { - "type": "string", - "description": "Topic name for the new chat room (e.g., 'Pulse Feb 2'). To edit the topic of an existing room, use [PATCH /api/chats](/api-reference/chat/update)." - } - } - }, - "CreateChatResponse": { - "type": "object", - "required": [ - "status", - "chat" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "chat": { - "$ref": "#/components/schemas/ChatRoom", - "description": "The created chat room object" - } - } - }, - "CreateChatErrorResponse": { - "type": "object", - "required": [ - "status", - "message" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "message": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "UpdateChatRequest": { - "type": "object", - "required": [ - "chatId", - "topic" - ], - "properties": { - "chatId": { - "type": "string", - "format": "uuid", - "description": "The unique identifier (UUID) of the chat room to update" - }, - "topic": { - "type": "string", - "minLength": 3, - "maxLength": 50, - "description": "The new display name for the chat room. Must be between 3 and 50 characters." - } - } - }, - "UpdateChatResponse": { - "type": "object", - "required": [ - "status", - "chat" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "chat": { - "$ref": "#/components/schemas/ChatRoom", - "description": "The updated chat room object" - } - } - }, - "UpdateChatErrorResponse": { - "type": "object", - "required": [ - "status", - "message" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "message": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "DeleteChatRequest": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "The unique identifier (UUID) of the chat room to delete." - } - } - }, - "DeleteChatResponse": { - "type": "object", - "required": [ - "status", - "id", - "message" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "id": { - "type": "string", - "format": "uuid", - "description": "The UUID of the deleted chat room." - }, - "message": { - "type": "string", - "description": "Success message describing the deletion result." - } - } - }, - "DeleteChatErrorResponse": { - "type": "object", - "required": [ - "status", - "error" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong." - } - } - }, - "UIMessage": { - "type": "object", - "description": "A message in the chat conversation. See https://ai-sdk.dev/docs/reference/ai-sdk-core/ui-message for details.", - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for the message" - }, - "role": { - "type": "string", - "enum": [ - "user", - "assistant", - "system" - ], - "description": "The role of the message sender" - }, - "content": { - "type": "string", - "description": "The text content of the message" - } - } - }, - "ChatGenerateRequest": { - "type": "object", - "description": "Request body for chat generation. Exactly one of 'prompt' or 'messages' must be provided.", - "properties": { - "prompt": { - "type": "string", - "description": "Single text prompt for the assistant. Required if 'messages' is not provided." - }, - "messages": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UIMessage" - }, - "description": "Array of UIMessage objects for context. Required if 'prompt' is not provided." - }, - "artistId": { - "type": "string", - "format": "uuid", - "description": "The unique identifier of the artist (optional)" - }, - "model": { - "type": "string", - "description": "The AI model to use for text generation (optional)", - "example": "openai/gpt-5-mini" - }, - "excludeTools": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Array of tool names to exclude from execution", - "example": [ - "create_scheduled_actions" - ] - }, - "roomId": { - "type": "string", - "format": "uuid", - "description": "UUID of the chat room. If not provided, one will be generated automatically." - }, - "topic": { - "type": "string", - "description": "Topic name for the new chat room (e.g., 'Pulse Feb 2'). Only applies when creating a new room - ignored if room already exists. To edit the topic of an existing room, use [PATCH /api/chats](/api-reference/chat/update)." - } - } - }, - "ContentPart": { - "type": "object", - "description": "A part of the response content. See https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-text#content for details.", - "properties": { - "type": { - "type": "string", - "enum": [ - "text", - "tool-call", - "tool-result" - ], - "description": "The type of content part" - }, - "text": { - "type": "string", - "description": "The text content (present when type is 'text')" - } - } - }, - "ChatGenerateUsage": { - "type": "object", - "description": "Token usage information with detailed breakdown", - "properties": { - "inputTokens": { - "type": "integer", - "description": "Number of input tokens processed" - }, - "outputTokens": { - "type": "integer", - "description": "Number of output tokens generated" - }, - "totalTokens": { - "type": "integer", - "description": "Total tokens used (input + output)" - }, - "reasoningTokens": { - "type": "integer", - "description": "Number of reasoning tokens used" - }, - "cachedInputTokens": { - "type": "integer", - "description": "Number of cached input tokens" - } - } - }, - "ChatGenerateResponseMeta": { - "type": "object", - "description": "Additional response metadata", - "properties": { - "messages": { - "type": "array", - "items": { - "type": "object" - }, - "description": "Response messages" - }, - "headers": { - "type": "object", - "description": "Response headers" - }, - "body": { - "type": "object", - "description": "Response body" - } - } - }, - "ChatGenerateResponse": { - "type": "object", - "description": "Response from the chat generation endpoint", - "properties": { - "text": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ContentPart" - }, - "description": "Array of content parts from the AI model response" - }, - "reasoningText": { - "type": "string", - "nullable": true, - "description": "Optional reasoning or explanation for the response" - }, - "sources": { - "type": "array", - "items": { - "type": "object" - }, - "description": "Optional array of sources used for the response" - }, - "finishReason": { - "type": "string", - "description": "The reason why the generation finished", - "example": "stop" - }, - "usage": { - "$ref": "#/components/schemas/ChatGenerateUsage", - "description": "Token usage information" - }, - "response": { - "$ref": "#/components/schemas/ChatGenerateResponseMeta", - "description": "Additional response metadata" - } - } - }, - "ChatGenerateErrorResponse": { - "type": "object", - "required": [ - "status", - "message" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "message": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "ChatStreamRequest": { - "type": "object", - "description": "Request body for chat streaming. Exactly one of 'prompt' or 'messages' must be provided.", - "properties": { - "prompt": { - "type": "string", - "description": "Single text prompt for the assistant. Required if 'messages' is not provided." - }, - "messages": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UIMessage" - }, - "description": "Array of UIMessage objects for context. Required if 'prompt' is not provided." - }, - "artistId": { - "type": "string", - "format": "uuid", - "description": "The unique identifier of the artist (optional)" - }, - "model": { - "type": "string", - "description": "The AI model to use for text generation (optional)", - "example": "openai/gpt-5-mini" - }, - "excludeTools": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Array of tool names to exclude from execution", - "example": [ - "create_scheduled_actions" - ] - }, - "roomId": { - "type": "string", - "format": "uuid", - "description": "UUID of the chat room. If not provided, one will be generated automatically." - }, - "topic": { - "type": "string", - "description": "Topic name for the new chat room (e.g., 'Pulse Feb 2'). Only applies when creating a new room - ignored if room already exists. To edit the topic of an existing room, use [PATCH /api/chats](/api-reference/chat/update)." - } - } - }, - "ChatStreamErrorResponse": { - "type": "object", - "required": [ - "status", - "message" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "message": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "Organization": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the membership record" - }, - "organization_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the organization account" - }, - "organization_name": { - "type": "string", - "description": "Display name of the organization" - }, - "organization_image": { - "type": "string", - "nullable": true, - "description": "Organization logo/image URL" - } - } - }, - "GetOrganizationsResponse": { - "type": "object", - "required": [ - "status", - "organizations" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "organizations": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Organization" - }, - "description": "List of organizations the account belongs to" - } - } - }, - "OrganizationsErrorResponse": { - "type": "object", - "required": [ - "status", - "message" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "message": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "CreateOrganizationRequest": { - "type": "object", - "required": [ - "name", - "accountId" - ], - "properties": { - "name": { - "type": "string", - "description": "The name of the organization to create", - "example": "My New Label" - }, - "accountId": { - "type": "string", - "format": "uuid", - "description": "The account ID of the creator", - "example": "123e4567-e89b-12d3-a456-426614174000" - } - } - }, - "CreatedOrganization": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the new organization account" - }, - "name": { - "type": "string", - "description": "Name of the organization" - } - } - }, - "CreateOrganizationResponse": { - "type": "object", - "required": [ - "status", - "organization" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "organization": { - "$ref": "#/components/schemas/CreatedOrganization", - "description": "The created organization" - } - } - }, - "CreateWorkspaceRequest": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of the workspace (defaults to \"Untitled\")" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the account to create the workspace for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, the workspace is created for the API key's own account." - }, - "organization_id": { - "type": "string", - "format": "uuid", - "description": "Organization to link the workspace to" - } - } - }, - "CreateWorkspaceResponse": { - "type": "object", - "required": [ - "workspace" - ], - "properties": { - "workspace": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid" - }, - "name": { - "type": "string" - }, - "account_id": { - "type": "string", - "format": "uuid" - }, - "isWorkspace": { - "type": "boolean" - } - } - } - } - }, - "AddArtistToOrganizationRequest": { - "type": "object", - "required": [ - "artistId", - "organizationId" - ], - "properties": { - "artistId": { - "type": "string", - "format": "uuid", - "description": "The account ID of the artist to add", - "example": "artist-account-uuid" - }, - "organizationId": { - "type": "string", - "format": "uuid", - "description": "The account ID of the organization", - "example": "org-account-uuid" - } - } - }, - "AddArtistToOrganizationResponse": { - "type": "object", - "required": [ - "status", - "id" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the created artist-organization link" - } - } - }, - "SpotifyImage": { - "type": "object", - "properties": { - "url": { - "type": "string", - "description": "The source URL of the image" - }, - "height": { - "type": "integer", - "nullable": true, - "description": "The image height in pixels" - }, - "width": { - "type": "integer", - "nullable": true, - "description": "The image width in pixels" - } - } - }, - "SpotifyExternalUrls": { - "type": "object", - "properties": { - "spotify": { - "type": "string", - "description": "The Spotify URL for the object" - } - } - }, - "SpotifyFollowers": { - "type": "object", - "properties": { - "href": { - "type": "string", - "nullable": true, - "description": "This will always be set to null" - }, - "total": { - "type": "integer", - "description": "The total number of followers" - } - } - }, - "SpotifyArtistObject": { - "type": "object", - "properties": { - "external_urls": { - "$ref": "#/components/schemas/SpotifyExternalUrls" - }, - "followers": { - "$ref": "#/components/schemas/SpotifyFollowers" - }, - "genres": { - "type": "array", - "items": { - "type": "string" - }, - "description": "A list of the genres the artist is associated with" - }, - "href": { - "type": "string", - "description": "A link to the Web API endpoint providing full details" - }, - "id": { - "type": "string", - "description": "The Spotify ID for the artist" - }, - "images": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpotifyImage" - }, - "description": "Images of the artist in various sizes" - }, - "name": { - "type": "string", - "description": "The name of the artist" - }, - "popularity": { - "type": "integer", - "description": "The popularity of the artist (0-100)" - }, - "type": { - "type": "string", - "enum": [ - "artist" - ], - "description": "The object type, always 'artist'" - }, - "uri": { - "type": "string", - "description": "The Spotify URI for the artist" - } - } - }, - "SpotifySimplifiedArtist": { - "type": "object", - "properties": { - "external_urls": { - "$ref": "#/components/schemas/SpotifyExternalUrls" - }, - "href": { - "type": "string", - "description": "A link to the Web API endpoint providing full details" - }, - "id": { - "type": "string", - "description": "The Spotify ID for the artist" - }, - "name": { - "type": "string", - "description": "The name of the artist" - }, - "type": { - "type": "string", - "enum": [ - "artist" - ], - "description": "The object type, always 'artist'" - }, - "uri": { - "type": "string", - "description": "The Spotify URI for the artist" - } - } - }, - "SpotifyArtistsPaginated": { - "type": "object", - "properties": { - "href": { - "type": "string", - "description": "A link to the Web API endpoint returning the full result" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpotifyArtistObject" - }, - "description": "List of artist objects" - }, - "limit": { - "type": "integer", - "description": "The maximum number of items in the response" - }, - "next": { - "type": "string", - "nullable": true, - "description": "URL to the next page of items" - }, - "offset": { - "type": "integer", - "description": "The offset of the items returned" - }, - "previous": { - "type": "string", - "nullable": true, - "description": "URL to the previous page of items" - }, - "total": { - "type": "integer", - "description": "The total number of items available" - } - } - }, - "SpotifySearchResponse": { - "type": "object", - "properties": { - "artists": { - "$ref": "#/components/schemas/SpotifyArtistsPaginated", - "description": "Search results for artists (if type includes artist)" - }, - "albums": { - "type": "object", - "description": "Search results for albums (if type includes album)" - }, - "tracks": { - "type": "object", - "description": "Search results for tracks (if type includes track)" - }, - "playlists": { - "type": "object", - "description": "Search results for playlists (if type includes playlist)" - } - } - }, - "SpotifyGetArtistResponse": { - "type": "object", - "properties": { - "artist": { - "$ref": "#/components/schemas/SpotifyArtistObject", - "nullable": true, - "description": "The Spotify artist object (null if error)" - }, - "error": { - "type": "object", - "nullable": true, - "description": "Error object if request failed (null if successful)" - } - } - }, - "SpotifySimplifiedAlbum": { - "type": "object", - "properties": { - "album_type": { - "type": "string", - "enum": [ - "album", - "single", - "compilation" - ], - "description": "The type of the album" - }, - "total_tracks": { - "type": "integer", - "description": "The number of tracks in the album" - }, - "available_markets": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Markets in which the album is available" - }, - "external_urls": { - "$ref": "#/components/schemas/SpotifyExternalUrls" - }, - "href": { - "type": "string", - "description": "A link to the Web API endpoint providing full details" - }, - "id": { - "type": "string", - "description": "The Spotify ID for the album" - }, - "images": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpotifyImage" - }, - "description": "The cover art for the album in various sizes" - }, - "name": { - "type": "string", - "description": "The name of the album" - }, - "release_date": { - "type": "string", - "description": "The date the album was first released" - }, - "release_date_precision": { - "type": "string", - "enum": [ - "year", - "month", - "day" - ], - "description": "The precision with which release_date value is known" - }, - "restrictions": { - "type": "object", - "properties": { - "reason": { - "type": "string", - "description": "The reason for the restriction" - } - }, - "description": "Included when a content restriction is applied" - }, - "type": { - "type": "string", - "enum": [ - "album" - ], - "description": "The object type, always 'album'" - }, - "uri": { - "type": "string", - "description": "The Spotify URI for the album" - }, - "artists": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpotifySimplifiedArtist" - }, - "description": "The artists of the album" - }, - "album_group": { - "type": "string", - "enum": [ - "album", - "single", - "compilation", - "appears_on" - ], - "description": "The field to distinguish albums by various groups" - } - } - }, - "SpotifyArtistAlbumsResponse": { - "type": "object", - "properties": { - "href": { - "type": "string", - "description": "A link to the Web API endpoint returning the full result" - }, - "limit": { - "type": "integer", - "description": "The maximum number of items in the response" - }, - "next": { - "type": "string", - "nullable": true, - "description": "URL to the next page of items" - }, - "offset": { - "type": "integer", - "description": "The offset of the items returned" - }, - "previous": { - "type": "string", - "nullable": true, - "description": "URL to the previous page of items" - }, - "total": { - "type": "integer", - "description": "The total number of items available" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpotifySimplifiedAlbum" - }, - "description": "Array of simplified album objects" - } - } - }, - "SpotifyTrack": { - "type": "object", - "properties": { - "album": { - "$ref": "#/components/schemas/SpotifySimplifiedAlbum", - "description": "The album the track appears on" - }, - "artists": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpotifySimplifiedArtist" - }, - "description": "Artists who performed the track" - }, - "available_markets": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Markets in which the track is available" - }, - "disc_number": { - "type": "integer", - "description": "Disc number the track is on" - }, - "duration_ms": { - "type": "integer", - "description": "Track length in milliseconds" - }, - "explicit": { - "type": "boolean", - "description": "Whether the track has explicit lyrics" - }, - "external_ids": { - "type": "object", - "properties": { - "isrc": { - "type": "string", - "description": "International Standard Recording Code" - }, - "ean": { - "type": "string", - "description": "International Article Number" - }, - "upc": { - "type": "string", - "description": "Universal Product Code" - } - }, - "description": "Known external IDs for the track" - }, - "external_urls": { - "$ref": "#/components/schemas/SpotifyExternalUrls" - }, - "href": { - "type": "string", - "description": "Link to the Web API endpoint with full details" - }, - "id": { - "type": "string", - "description": "Spotify ID for the track" - }, - "is_playable": { - "type": "boolean", - "description": "If true, the track is playable in the given market" - }, - "linked_from": { - "type": "object", - "description": "Information about the originally requested track when track relinking is applied" - }, - "restrictions": { - "type": "object", - "properties": { - "reason": { - "type": "string", - "description": "The reason for the restriction" - } - }, - "description": "Content restriction information" - }, - "name": { - "type": "string", - "description": "Track name" - }, - "popularity": { - "type": "integer", - "description": "Popularity score (0-100)" - }, - "preview_url": { - "type": "string", - "nullable": true, - "description": "URL to a 30 second preview, if available" - }, - "track_number": { - "type": "integer", - "description": "Track number on the album" - }, - "type": { - "type": "string", - "enum": [ - "track" - ], - "description": "The object type, always 'track'" - }, - "uri": { - "type": "string", - "description": "The Spotify URI for the track" - }, - "is_local": { - "type": "boolean", - "description": "Whether the track is from a local file" - } - } - }, - "SpotifyArtistTopTracksResponse": { - "type": "object", - "properties": { - "tracks": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpotifyTrack" - }, - "description": "Array of track objects" - } - } - }, - "SpotifySimplifiedTrack": { - "type": "object", - "properties": { - "artists": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpotifySimplifiedArtist" - }, - "description": "The artists who performed the track" - }, - "available_markets": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Markets in which the track is available" - }, - "disc_number": { - "type": "integer", - "description": "Disc number the track is on" - }, - "duration_ms": { - "type": "integer", - "description": "Track length in milliseconds" - }, - "explicit": { - "type": "boolean", - "description": "Whether the track has explicit lyrics" - }, - "external_urls": { - "$ref": "#/components/schemas/SpotifyExternalUrls" - }, - "href": { - "type": "string", - "description": "Link to the Web API endpoint" - }, - "id": { - "type": "string", - "description": "Spotify ID for the track" - }, - "is_playable": { - "type": "boolean", - "description": "If true, the track is playable" - }, - "linked_from": { - "type": "object", - "description": "Track relinking info" - }, - "restrictions": { - "type": "object", - "properties": { - "reason": { - "type": "string" - } - } - }, - "name": { - "type": "string", - "description": "Track name" - }, - "preview_url": { - "type": "string", - "nullable": true, - "description": "URL to a 30 second preview" - }, - "track_number": { - "type": "integer", - "description": "Track number on the album" - }, - "type": { - "type": "string", - "enum": [ - "track" - ] - }, - "uri": { - "type": "string", - "description": "Spotify URI for the track" - }, - "is_local": { - "type": "boolean", - "description": "Whether from a local file" - } - } - }, - "SpotifyAlbumTracks": { - "type": "object", - "properties": { - "href": { - "type": "string", - "description": "A link to the Web API endpoint" - }, - "limit": { - "type": "integer", - "description": "The maximum number of items in the response" - }, - "next": { - "type": "string", - "nullable": true, - "description": "URL to the next page of items" - }, - "offset": { - "type": "integer", - "description": "The offset of the items returned" - }, - "previous": { - "type": "string", - "nullable": true, - "description": "URL to the previous page" - }, - "total": { - "type": "integer", - "description": "Total number of items available" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpotifySimplifiedTrack" - }, - "description": "Array of simplified track objects" - } - } - }, - "SpotifyCopyright": { - "type": "object", - "properties": { - "text": { - "type": "string", - "description": "The copyright text" - }, - "type": { - "type": "string", - "description": "The type of copyright" - } - } - }, - "SpotifyAlbum": { - "type": "object", - "properties": { - "album_type": { - "type": "string", - "enum": [ - "album", - "single", - "compilation" - ], - "description": "The type of the album" - }, - "total_tracks": { - "type": "integer", - "description": "The number of tracks in the album" - }, - "available_markets": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Markets in which the album is available" - }, - "external_urls": { - "$ref": "#/components/schemas/SpotifyExternalUrls" - }, - "href": { - "type": "string", - "description": "A link to the Web API endpoint providing full details" - }, - "id": { - "type": "string", - "description": "The Spotify ID for the album" - }, - "images": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpotifyImage" - }, - "description": "The cover art for the album in various sizes" - }, - "name": { - "type": "string", - "description": "The name of the album" - }, - "release_date": { - "type": "string", - "description": "The date the album was first released" - }, - "release_date_precision": { - "type": "string", - "enum": [ - "year", - "month", - "day" - ], - "description": "The precision with which release_date value is known" - }, - "restrictions": { - "type": "object", - "properties": { - "reason": { - "type": "string" - } - }, - "description": "Included when a content restriction is applied" - }, - "type": { - "type": "string", - "enum": [ - "album" - ], - "description": "The object type, always 'album'" - }, - "uri": { - "type": "string", - "description": "The Spotify URI for the album" - }, - "artists": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpotifySimplifiedArtist" - }, - "description": "The artists of the album" - }, - "tracks": { - "$ref": "#/components/schemas/SpotifyAlbumTracks", - "description": "The tracks of the album" - }, - "copyrights": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpotifyCopyright" - }, - "description": "Copyright statements of the album" - }, - "external_ids": { - "type": "object", - "properties": { - "isrc": { - "type": "string" - }, - "ean": { - "type": "string" - }, - "upc": { - "type": "string" - } - }, - "description": "Known external IDs for the album" - }, - "genres": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Deprecated. Always empty." - }, - "label": { - "type": "string", - "description": "The label associated with the album" - }, - "popularity": { - "type": "integer", - "description": "Popularity of the album (0-100)" - } - } - }, - "SpotifyErrorResponse": { - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "status": { - "type": "integer", - "description": "HTTP status code" - }, - "message": { - "type": "string", - "description": "Error message" - } - }, - "description": "Error details" - } - } - }, - "TwitterPhoto": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Photo ID" - }, - "url": { - "type": "string", - "description": "URL of the photo" - } - } - }, - "TwitterVideo": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Video ID" - }, - "preview": { - "type": "string", - "description": "URL of the video preview image" - }, - "url": { - "type": "string", - "description": "URL of the video" - } - } - }, - "Tweet": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Tweet ID" - }, - "text": { - "type": "string", - "description": "Tweet text content" - }, - "username": { - "type": "string", - "description": "Username of the tweet author" - }, - "timestamp": { - "type": "integer", - "description": "Unix timestamp (ms) of when the tweet was posted" - }, - "createdAt": { - "type": "string", - "description": "ISO timestamp of when the tweet was posted" - }, - "isReply": { - "type": "boolean", - "description": "Whether the tweet is a reply" - }, - "isRetweet": { - "type": "boolean", - "description": "Whether the tweet is a retweet" - }, - "likes": { - "type": "integer", - "description": "Number of likes" - }, - "retweetCount": { - "type": "integer", - "description": "Number of retweets" - }, - "replies": { - "type": "integer", - "description": "Number of replies" - }, - "photos": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TwitterPhoto" - }, - "description": "Array of photo objects" - }, - "videos": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TwitterVideo" - }, - "description": "Array of video objects" - }, - "urls": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Array of URLs included in the tweet" - }, - "permanentUrl": { - "type": "string", - "description": "Permanent URL to the tweet" - }, - "quotedStatusId": { - "type": "string", - "description": "ID of the quoted tweet (if applicable)" - }, - "inReplyToStatusId": { - "type": "string", - "description": "ID of the tweet this is replying to (if applicable)" - }, - "hashtags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Array of hashtags in the tweet" - } - } - }, - "TwitterSearchResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "description": "Status of the request", - "enum": [ - "success", - "error" - ] - }, - "tweets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Tweet" - }, - "description": "List of tweet objects" - } - } - }, - "TwitterTrendsResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "description": "Status of the request", - "enum": [ - "success", - "error" - ] - }, - "trends": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of current trending topics on Twitter" - } - } - }, - "TwitterErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "message": { - "type": "string", - "description": "Error message" - } - } - }, - "SocialScrapeRequest": { - "type": "object", - "required": [ - "social_id" - ], - "properties": { - "social_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the social profile to scrape. Obtain this from the Get Artist Socials API." - } - } - }, - "SocialPost": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the social's social_posts record" - }, - "post_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the social's posts record" - }, - "social_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the social's socials record" - }, - "post_url": { - "type": "string", - "description": "Direct URL to the post on the platform" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of when the post data was last updated" - } - } - }, - "SocialPostsPagination": { - "type": "object", - "properties": { - "total_count": { - "type": "integer", - "description": "Total number of posts available" - }, - "page": { - "type": "integer", - "description": "Current page number" - }, - "limit": { - "type": "integer", - "description": "Number of posts per page" - }, - "total_pages": { - "type": "integer", - "description": "Total number of pages available" - } - } - }, - "SocialPostsResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Status of the request" - }, - "posts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SocialPost" - }, - "description": "List of social media posts" - }, - "pagination": { - "$ref": "#/components/schemas/SocialPostsPagination" - } - } - }, - "SocialErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "message": { - "type": "string", - "description": "Error message" - } - } - }, - "GeneratedImage": { - "type": "object", - "description": "A generated image file from the AI model", - "properties": { - "base64": { - "type": "string", - "description": "Image file as a base64 encoded string" - }, - "uint8Array": { - "type": "array", - "items": { - "type": "integer" - }, - "description": "Image file as a Uint8Array (represented as array of numbers in JSON)" - }, - "mediaType": { - "type": "string", - "description": "The IANA media type of the file (e.g., 'image/png', 'image/jpeg')" - } - } - }, - "ImageResponseMeta": { - "type": "object", - "description": "Response metadata from the AI provider", - "properties": { - "finishReason": { - "type": "string", - "description": "Reason the generation finished (e.g., 'stop')" - } - } - }, - "ImageProviderMetadata": { - "type": "object", - "description": "Metadata from the AI provider about the generation", - "properties": { - "model": { - "type": "string", - "description": "The AI model used for generation (e.g., 'dall-e-3', 'gpt-image-1')" - }, - "size": { - "type": "string", - "description": "The size of the generated image (e.g., '1024x1024')" - } - } - }, - "ImageUsage": { - "type": "object", - "description": "Token usage information for the image generation", - "properties": { - "promptTokens": { - "type": "integer", - "description": "Number of tokens used in the prompt" - }, - "completionTokens": { - "type": "integer", - "description": "Number of tokens used in the completion (typically 0 for image generation)" - }, - "totalTokens": { - "type": "integer", - "description": "Total tokens used" - } - } - }, - "ArweaveTransaction": { - "type": "object", - "description": "Arweave transaction object for the stored image", - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for the Arweave transaction" - }, - "last_tx": { - "type": "string", - "description": "Last transaction reference" - }, - "owner": { - "type": "string", - "description": "Owner address of the transaction" - }, - "tags": { - "type": "array", - "items": { - "type": "object" - }, - "description": "Tags associated with the transaction" - }, - "target": { - "type": "string", - "description": "Target address (empty for data transactions)" - }, - "quantity": { - "type": "string", - "description": "Amount transferred (typically '0' for data transactions)" - }, - "data": { - "type": "string", - "description": "Transaction data (may be empty in response)" - }, - "reward": { - "type": "string", - "description": "Mining reward for the transaction" - }, - "signature": { - "type": "string", - "description": "Transaction signature" - }, - "format": { - "type": "integer", - "description": "Transaction format version" - } - } - }, - "InProcessMoment": { - "type": "object", - "description": "In Process moment metadata for provenance and ownership tracking", - "properties": { - "contractAddress": { - "type": "string", - "description": "Smart contract address for the moment" - }, - "tokenId": { - "type": "string", - "description": "Token ID of the minted moment" - }, - "hash": { - "type": "string", - "description": "Transaction hash of the moment mint" - }, - "chainId": { - "type": "integer", - "description": "Chain ID (e.g., 8453 for Base)" - } - } - }, - "ImageGenerationResponse": { - "type": "object", - "description": "Response from the image generation endpoint, extending Experimental_GenerateImageResult from the AI SDK", - "properties": { - "images": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeneratedImage" - }, - "description": "Array of generated image objects" - }, - "warnings": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Array of warning messages, if any" - }, - "responses": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ImageResponseMeta" - }, - "description": "Array of response metadata from the AI provider" - }, - "providerMetadata": { - "$ref": "#/components/schemas/ImageProviderMetadata" - }, - "usage": { - "$ref": "#/components/schemas/ImageUsage" - }, - "imageUrl": { - "type": "string", - "description": "Permanent Arweave URL where the image is stored" - }, - "arweaveResult": { - "$ref": "#/components/schemas/ArweaveTransaction" - }, - "moment": { - "$ref": "#/components/schemas/InProcessMoment" - } - } - }, - "ImageGenerationErrorResponse": { - "type": "object", - "properties": { - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "TranscribeAudioRequest": { - "type": "object", - "required": [ - "audio_url", - "account_id", - "artist_account_id" - ], - "properties": { - "audio_url": { - "type": "string", - "description": "Public URL to the audio file (mp3, wav, m4a, webm)", - "example": "https://example.com/song.mp3" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "Owner account ID for file storage", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "artist_account_id": { - "type": "string", - "format": "uuid", - "description": "Artist account ID for file storage", - "example": "550e8400-e29b-41d4-a716-446655440001" - }, - "title": { - "type": "string", - "description": "Optional title for the audio and transcription files", - "example": "My Song" - }, - "include_timestamps": { - "type": "boolean", - "description": "Whether to include timestamps in the markdown transcript", - "default": false - } - } - }, - "TranscribeFileInfo": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the file record in the database" - }, - "fileName": { - "type": "string", - "description": "Name of the saved file" - }, - "storageKey": { - "type": "string", - "description": "Storage path in Supabase Storage" - } - } - }, - "TranscribeAudioResponse": { - "type": "object", - "required": [ - "success", - "audioFile", - "transcriptFile", - "text" - ], - "properties": { - "success": { - "type": "boolean", - "description": "Whether the transcription was successful" - }, - "audioFile": { - "$ref": "#/components/schemas/TranscribeFileInfo", - "description": "Information about the saved audio file" - }, - "transcriptFile": { - "$ref": "#/components/schemas/TranscribeFileInfo", - "description": "Information about the saved transcript file" - }, - "text": { - "type": "string", - "description": "The full transcription text" - }, - "language": { - "type": "string", - "description": "Detected language code (e.g., 'en', 'es', 'fr')" - } - } - }, - "TranscribeAudioErrorResponse": { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "SongArtist": { - "type": "object", - "description": "Artist associated with a song", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "Unique identifier for the artist account" - }, - "name": { - "type": "string", - "nullable": true, - "description": "Name of the artist (can be null)" - }, - "timestamp": { - "type": "integer", - "nullable": true, - "description": "Timestamp associated with the artist account (can be null)" - } - } - }, - "Song": { - "type": "object", - "description": "A song with its metadata and associated artists", - "properties": { - "isrc": { - "type": "string", - "description": "International Standard Recording Code (primary key)" - }, - "name": { - "type": "string", - "description": "Name of the song" - }, - "album": { - "type": "string", - "description": "Name of the album the song belongs to" - }, - "notes": { - "type": "string", - "description": "Notes for the song" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of when the song data was last updated" - }, - "artists": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SongArtist" - }, - "description": "Array of artist objects associated with this song" - } - } - }, - "SongsResponse": { - "type": "object", - "description": "Response containing songs data", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Status of the request" - }, - "songs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Song" - }, - "description": "Array of song objects with artist information" - }, - "error": { - "type": "string", - "description": "Error message (only present if status is 'error')" - } - } - }, - "SongsErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "CreateSongInput": { - "type": "object", - "required": [ - "isrc" - ], - "properties": { - "isrc": { - "type": "string", - "description": "International Standard Recording Code of the song to create or fetch" - }, - "name": { - "type": "string", - "description": "Optional. Song name, applied only if internal search cannot find valid info" - }, - "album": { - "type": "string", - "description": "Optional. Album name, applied only if internal search cannot find valid info" - }, - "notes": { - "type": "string", - "description": "Optional. Notes for the song, applied only if internal search cannot find valid info" - }, - "artists": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Optional array of artist names, applied only if internal search cannot find valid info" - } - } - }, - "CreateSongsRequest": { - "type": "object", - "required": [ - "songs" - ], - "properties": { - "songs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CreateSongInput" - }, - "description": "Array of song inputs for bulk create/fetch" - } - } - }, - "Catalog": { - "type": "object", - "description": "A catalog with its metadata", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "Unique identifier for the catalog" - }, - "name": { - "type": "string", - "description": "Name of the catalog" - }, - "created_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of when the catalog was created" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of when the catalog was last updated" - } - } - }, - "CatalogsResponse": { - "type": "object", - "description": "Response containing catalogs data", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Status of the request" - }, - "catalogs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Catalog" - }, - "description": "Array of catalog objects" - }, - "error": { - "type": "string", - "description": "Error message (only present if status is 'error')" - } - } - }, - "CatalogsErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "CreateCatalogInput": { - "type": "object", - "required": [ - "account_id" - ], - "properties": { - "account_id": { - "type": "string", - "format": "uuid", - "description": "The account to associate the catalog with" - }, - "name": { - "type": "string", - "description": "Catalog name to create if catalog_id is omitted" - }, - "catalog_id": { - "type": "string", - "format": "uuid", - "description": "Existing catalog ID to link to the account" - } - } - }, - "CreateCatalogsRequest": { - "type": "object", - "required": [ - "catalogs" - ], - "properties": { - "catalogs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CreateCatalogInput" - }, - "description": "Array of catalog inputs for bulk create/link operations" - } - } - }, - "DeleteCatalogInput": { - "type": "object", - "required": [ - "catalog_id", - "account_id" - ], - "properties": { - "catalog_id": { - "type": "string", - "format": "uuid", - "description": "Catalog ID to remove" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "Account ID whose relationship will be removed" - } - } - }, - "DeleteCatalogsRequest": { - "type": "object", - "required": [ - "catalogs" - ], - "properties": { - "catalogs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DeleteCatalogInput" - }, - "description": "Array of catalog-account pairs to remove" - } - } - }, - "CatalogSong": { - "type": "object", - "description": "A song within a catalog with its metadata and associated artists", - "properties": { - "catalog_id": { - "type": "string", - "format": "uuid", - "description": "Catalog ID this song entry is associated with" - }, - "isrc": { - "type": "string", - "description": "International Standard Recording Code (primary key)" - }, - "name": { - "type": "string", - "description": "Name of the song" - }, - "album": { - "type": "string", - "description": "Name of the album the song belongs to" - }, - "lyrics": { - "type": "string", - "description": "Full lyrics of the song" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of when the song data was last updated" - }, - "artists": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SongArtist" - }, - "description": "Array of artist objects associated with this song" - } - } - }, - "CatalogSongsPagination": { - "type": "object", - "description": "Pagination metadata for catalog songs response", - "properties": { - "total_count": { - "type": "integer", - "description": "Total number of songs in the catalog" - }, - "page": { - "type": "integer", - "description": "Current page number" - }, - "limit": { - "type": "integer", - "description": "Number of songs per page" - }, - "total_pages": { - "type": "integer", - "description": "Total number of pages available" - } - } - }, - "CatalogSongsResponse": { - "type": "object", - "description": "Response containing catalog songs data with pagination", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Status of the request" - }, - "songs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CatalogSong" - }, - "description": "Array of song objects with artist information" - }, - "pagination": { - "$ref": "#/components/schemas/CatalogSongsPagination", - "description": "Pagination metadata for the response" - }, - "error": { - "type": "string", - "description": "Error message (only present if status is 'error')" - } - } - }, - "CatalogSongsErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "AddCatalogSongInput": { - "type": "object", - "required": [ - "catalog_id", - "isrc" - ], - "properties": { - "catalog_id": { - "type": "string", - "format": "uuid", - "description": "Catalog ID to which the song will be added" - }, - "isrc": { - "type": "string", - "description": "Song ISRC to associate to the catalog" - }, - "name": { - "type": "string", - "description": "Optional. Applied only if internal search cannot find valid info for ISRC" - }, - "album": { - "type": "string", - "description": "Optional. Applied only if internal search cannot find valid info for ISRC" - }, - "notes": { - "type": "string", - "description": "Optional. Applied only if internal search cannot find valid info for ISRC" - }, - "artists": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Optional array of artist names. Applied only if internal search lacks info" - } - } - }, - "AddCatalogSongsRequest": { - "type": "object", - "required": [ - "songs" - ], - "properties": { - "songs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AddCatalogSongInput" - }, - "description": "Array of songs for batch updates" - } - } - }, - "DeleteCatalogSongInput": { - "type": "object", - "required": [ - "catalog_id", - "isrc" - ], - "properties": { - "catalog_id": { - "type": "string", - "format": "uuid", - "description": "Catalog ID from which the song will be removed" - }, - "isrc": { - "type": "string", - "description": "Song ISRC to remove from the catalog" - } - } - }, - "DeleteCatalogSongsRequest": { - "type": "object", - "required": [ - "songs" - ], - "properties": { - "songs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DeleteCatalogSongInput" - }, - "description": "Array of songs for batch deletes" - } - } - }, - "ArtistFan": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for the fan's social profile" - }, - "username": { - "type": "string", - "description": "Username or handle on the platform" - }, - "avatar": { - "type": "string", - "description": "URL to the fan's avatar/profile image" - }, - "profile_url": { - "type": "string", - "description": "Full URL to the fan's profile on the platform" - }, - "region": { - "type": "string", - "description": "Geographic region or location of the fan" - }, - "bio": { - "type": "string", - "description": "Fan's biography or profile description" - }, - "followerCount": { - "type": "integer", - "description": "Number of followers the fan has" - }, - "followingCount": { - "type": "integer", - "description": "Number of accounts the fan is following" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of when the fan data was last updated" - } - } - }, - "ArtistFansPagination": { - "type": "object", - "properties": { - "total_count": { - "type": "integer", - "description": "Total number of records available" - }, - "page": { - "type": "integer", - "description": "Current page number" - }, - "limit": { - "type": "integer", - "description": "Number of records per page" - }, - "total_pages": { - "type": "integer", - "description": "Total number of pages available" - } - } - }, - "ArtistFansResponse": { - "type": "object", - "required": [ - "status", - "fans", - "pagination" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "fans": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ArtistFan" - }, - "description": "List of social profiles from fans across all platforms" - }, - "pagination": { - "$ref": "#/components/schemas/ArtistFansPagination", - "description": "Pagination metadata for the response" - } - } - }, - "ArtistFansErrorResponse": { - "type": "object", - "required": [ - "status", - "error" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "SegmentFan": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "Unique identifier for the fan_segments record" - }, - "username": { - "type": "string", - "description": "Username or handle on the platform" - }, - "avatar": { - "type": "string", - "description": "URL to the fan's avatar/profile image" - }, - "profile_url": { - "type": "string", - "description": "Full URL to the fan's profile on the platform" - }, - "segment_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the fan's segments record" - }, - "segment_name": { - "type": "string", - "description": "Name of the segment (e.g., 'Twitter Followers')" - }, - "fan_social_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the fan's socials media profile account" - }, - "region": { - "type": "string", - "description": "Geographic region or location of the fan" - }, - "bio": { - "type": "string", - "description": "Fan's biography or profile description" - }, - "follower_count": { - "type": "integer", - "description": "Number of followers the fan has" - }, - "following_count": { - "type": "integer", - "description": "Number of accounts the fan is following" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of when the fan data was last updated" - } - } - }, - "ArtistPost": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "Unique identifier for the post" - }, - "post_url": { - "type": "string", - "description": "Direct URL to the post on the social platform" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of when the post was last updated" - } - } - }, - "ArtistPostsPagination": { - "type": "object", - "properties": { - "total_count": { - "type": "integer", - "description": "Total number of posts available" - }, - "page": { - "type": "integer", - "description": "Current page number" - }, - "limit": { - "type": "integer", - "description": "Number of posts per page" - }, - "total_pages": { - "type": "integer", - "description": "Total number of pages available" - } - } - }, - "ArtistPostsResponse": { - "type": "object", - "required": [ - "status", - "posts", - "pagination" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "posts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ArtistPost" - }, - "description": "List of posts from the artist across all social platforms" - }, - "pagination": { - "$ref": "#/components/schemas/ArtistPostsPagination", - "description": "Pagination metadata for the response" - } - } - }, - "ArtistPostsErrorResponse": { - "type": "object", - "required": [ - "status", - "error" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "PostComment": { - "type": "object", - "required": [ - "id", - "post_id", - "social_id", - "comment", - "commented_at", - "username", - "profile_url", - "post_url" - ], - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the comment record" - }, - "post_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the post this comment belongs to" - }, - "social_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the social profile that made the comment" - }, - "comment": { - "type": "string", - "description": "Text content of the comment" - }, - "commented_at": { - "type": "string", - "format": "date-time", - "description": "ISO timestamp of when the comment was posted" - }, - "username": { - "type": "string", - "description": "Username of the commenter" - }, - "avatar": { - "type": "string", - "nullable": true, - "description": "URL to the commenter's avatar image" - }, - "profile_url": { - "type": "string", - "description": "URL to the commenter's profile" - }, - "post_url": { - "type": "string", - "description": "URL to the post where the comment was made" - }, - "region": { - "type": "string", - "nullable": true, - "description": "Geographic region of the commenter" - }, - "bio": { - "type": "string", - "nullable": true, - "description": "Commenter's biography or description" - }, - "follower_count": { - "type": "integer", - "nullable": true, - "description": "Number of followers the commenter has" - }, - "following_count": { - "type": "integer", - "nullable": true, - "description": "Number of accounts the commenter follows" - } - } - }, - "PostCommentsPagination": { - "type": "object", - "properties": { - "total_count": { - "type": "integer", - "description": "Total number of comments available" - }, - "page": { - "type": "integer", - "description": "Current page number" - }, - "limit": { - "type": "integer", - "description": "Number of comments per page" - }, - "total_pages": { - "type": "integer", - "description": "Total number of pages available" - } - } - }, - "PostCommentsResponse": { - "type": "object", - "required": [ - "status", - "comments", - "pagination" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "comments": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PostComment" - }, - "description": "List of comments for the specified post" - }, - "pagination": { - "$ref": "#/components/schemas/PostCommentsPagination", - "description": "Pagination metadata for the response" - } - } - }, - "PostCommentsErrorResponse": { - "type": "object", - "required": [ - "status", - "error" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "Comment": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "UUID of the comment" - }, - "post_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the associated post" - }, - "social_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the social profile who made the comment" - }, - "comment": { - "type": "string", - "description": "Comment text content" - }, - "commented_at": { - "type": "string", - "format": "date-time", - "description": "Timestamp with timezone of when the comment was made" - } - } - }, - "CommentsPagination": { - "type": "object", - "properties": { - "total_count": { - "type": "integer", - "description": "Total number of comments available" - }, - "page": { - "type": "integer", - "description": "Current page number" - }, - "limit": { - "type": "integer", - "description": "Number of comments per page" - }, - "total_pages": { - "type": "integer", - "description": "Total number of pages available" - } - } - }, - "CommentsResponse": { - "type": "object", - "required": [ - "status", - "comments", - "pagination" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "comments": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Comment" - }, - "description": "List of comments for the specified artist or post" - }, - "pagination": { - "$ref": "#/components/schemas/CommentsPagination", - "description": "Pagination metadata for the response" - } - } - }, - "CommentsErrorResponse": { - "type": "object", - "required": [ - "status", - "error" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "SegmentFansPagination": { - "type": "object", - "properties": { - "total_count": { - "type": "integer", - "description": "Total number of records available" - }, - "page": { - "type": "integer", - "description": "Current page number" - }, - "limit": { - "type": "integer", - "description": "Number of records per page" - }, - "total_pages": { - "type": "integer", - "description": "Total number of pages available" - } - } - }, - "SegmentFansResponse": { - "type": "object", - "required": [ - "status", - "fans", - "pagination" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "fans": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SegmentFan" - }, - "description": "List of social profiles from fans in the segment" - }, - "pagination": { - "$ref": "#/components/schemas/SegmentFansPagination", - "description": "Pagination metadata for the response" - } - } - }, - "SegmentFansErrorResponse": { - "type": "object", - "required": [ - "status", - "error" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "StripeSubscription": { - "type": "object", - "description": "A Stripe subscription object. For detailed information about all available properties, see the Stripe Subscription API documentation: https://docs.stripe.com/api/subscriptions/retrieve", - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for the subscription" - }, - "object": { - "type": "string", - "enum": [ - "subscription" - ], - "description": "String representing the object's type" - }, - "customer": { - "type": "string", - "description": "ID of the customer who owns this subscription" - }, - "status": { - "type": "string", - "enum": [ - "active", - "canceled", - "incomplete", - "incomplete_expired", - "past_due", - "trialing", - "unpaid" - ], - "description": "The status of the subscription" - }, - "currency": { - "type": "string", - "description": "Three-letter ISO currency code" - }, - "current_period_start": { - "type": "integer", - "description": "Start of the current period (Unix timestamp)" - }, - "current_period_end": { - "type": "integer", - "description": "End of the current period (Unix timestamp)" - }, - "cancel_at_period_end": { - "type": "boolean", - "description": "If true, the subscription will be canceled at the end of the current period" - }, - "created": { - "type": "integer", - "description": "Time at which the subscription was created (Unix timestamp)" - }, - "items": { - "type": "object", - "description": "List of subscription items, each with an attached price", - "properties": { - "object": { - "type": "string", - "enum": [ - "list" - ] - }, - "data": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "object": { - "type": "string", - "enum": [ - "subscription_item" - ] - }, - "price": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "currency": { - "type": "string" - }, - "unit_amount": { - "type": "integer", - "description": "Price amount in cents" - }, - "recurring": { - "type": "object", - "properties": { - "interval": { - "type": "string", - "enum": [ - "day", - "week", - "month", - "year" - ] - }, - "interval_count": { - "type": "integer" - } - } - } - } - }, - "quantity": { - "type": "integer" - } - } - } - }, - "has_more": { - "type": "boolean" - }, - "total_count": { - "type": "integer" - } - } - }, - "latest_invoice": { - "type": "string", - "description": "ID of the most recent invoice for this subscription" - }, - "livemode": { - "type": "boolean", - "description": "Indicates if in live mode (true) or test mode (false)" - }, - "metadata": { - "type": "object", - "description": "Set of key-value pairs attached to the subscription" - } - } - }, - "SubscriptionResponse": { - "type": "object", - "required": [ - "status", - "subscription" - ], - "description": "Response for standard accounts with Stripe subscriptions", - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "subscription": { - "$ref": "#/components/schemas/StripeSubscription", - "description": "The full Stripe subscription object" - } - } - }, - "EnterpriseSubscriptionResponse": { - "type": "object", - "required": [ - "status", - "isEnterprise" - ], - "description": "Response for accounts with enterprise plans", - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "isEnterprise": { - "type": "boolean", - "enum": [ - true - ], - "description": "Indicates that the account has an enterprise plan" - } - } - }, - "SubscriptionErrorResponse": { - "type": "object", - "required": [ - "status", - "error" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Status of the request" - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "CreateSandboxRequest": { - "type": "object", - "description": "Request body for creating a new sandbox. All fields are optional - if no command or prompt is provided, sandbox is created without triggering a command execution task. Use prompt as a shortcut to run OpenCode with a given prompt instead of specifying command/args manually.", - "properties": { - "command": { - "type": "string", - "minLength": 1, - "description": "The command to execute in the sandbox environment. If omitted, the sandbox is created without running any command.", - "example": "ls" - }, - "args": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Optional arguments to pass to the command.", - "example": [ - "-la", - "/home" - ] - }, - "cwd": { - "type": "string", - "description": "Optional working directory for command execution.", - "example": "/home/user" - }, - "prompt": { - "type": "string", - "minLength": 1, - "description": "A prompt to pass to OpenCode in the sandbox. When provided, the sandbox will execute `opencode run \"\"`. Cannot be used together with command.", - "example": "create a hello world index.html" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the account to create the sandbox for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, creates the sandbox for the API key's own account." - } - } - }, - "Sandbox": { - "type": "object", - "required": [ - "sandboxId", - "sandboxStatus", - "timeout", - "createdAt" - ], - "description": "A sandbox environment instance", - "properties": { - "sandboxId": { - "type": "string", - "description": "Unique identifier for the sandbox", - "example": "sbx_abc123def456" - }, - "sandboxStatus": { - "type": "string", - "enum": [ - "pending", - "running", - "stopping", - "stopped", - "failed" - ], - "description": "Current lifecycle state of the sandbox", - "example": "running" - }, - "timeout": { - "type": "integer", - "description": "Milliseconds remaining before the sandbox stops automatically", - "example": 300000 - }, - "createdAt": { - "type": "string", - "format": "date-time", - "description": "ISO 8601 timestamp when the sandbox was created", - "example": "2024-01-15T10:30:00.000Z" - }, - "runId": { - "type": "string", - "description": "Unique identifier for the command execution run. Only present if a command was provided when creating the sandbox. Use this with [GET /api/tasks/runs](/api-reference/tasks/runs) to check the status and retrieve results.", - "example": "run_xyz789abc123" - } - } - }, - "SandboxesResponse": { - "type": "object", - "required": [ - "status", - "sandboxes" - ], - "description": "Response containing sandbox information", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Status of the request" - }, - "sandboxes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Sandbox" - }, - "description": "Array of sandbox objects" - }, - "snapshot_id": { - "type": "string", - "description": "The account's saved snapshot ID used for creating new sandboxes. Null if no snapshot has been saved.", - "example": "snap_abc123def456", - "nullable": true - }, - "github_repo": { - "type": "string", - "description": "The GitHub repository URL associated with the account's sandbox environment. Used as the filesystem source when restoring sandboxes.", - "example": "https://github.com/username/repo", - "nullable": true - }, - "filetree": { - "type": "array", - "nullable": true, - "description": "The recursive file tree of the account's GitHub repository. Null if no github_repo is set or if the fetch fails.", - "items": { - "$ref": "#/components/schemas/FileTreeEntry" - } - }, - "error": { - "type": "string", - "description": "Error message (only present if status is error)" - } - } - }, - "SandboxErrorResponse": { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "type": "string", - "description": "Error message describing what went wrong", - "example": "Failed to create sandbox" - } - } - }, - "SandboxFileResponse": { - "type": "object", - "required": [ - "status", - "content" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the operation" - }, - "content": { - "type": "string", - "description": "The raw text content of the file" - } - } - }, - "UploadSandboxFilesRequest": { - "type": "object", - "required": [ - "files" - ], - "properties": { - "path": { - "type": "string", - "description": "The target directory path within the repository to upload files to. Defaults to the repository root if omitted.", - "example": "assets/images" - }, - "files": { - "type": "array", - "items": { - "type": "object", - "required": [ - "url", - "name" - ], - "properties": { - "url": { - "type": "string", - "format": "uri", - "description": "The URL of the file to upload", - "example": "https://example.com/files/album-cover.png" - }, - "name": { - "type": "string", - "description": "The filename to use when committing to the repository", - "example": "album-cover.png" - } - } - }, - "description": "Array of files to upload, each with a URL and target filename" - }, - "message": { - "type": "string", - "description": "Optional commit message. Defaults to 'Upload files via API'.", - "example": "Add new album artwork" - } - } - }, - "UploadSandboxFilesResponse": { - "type": "object", - "required": [ - "status", - "uploaded" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the operation" - }, - "uploaded": { - "type": "array", - "items": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "The full path of the uploaded file in the repository" - }, - "sha": { - "type": "string", - "description": "The git SHA of the created/updated file" - } - } - }, - "description": "Array of uploaded file details" - } - } - }, - "SetupSandboxRequest": { - "type": "object", - "properties": { - "account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the account to set up the sandbox for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, sets up the sandbox for the API key's own account." - } - } - }, - "SetupSandboxResponse": { - "type": "object", - "required": [ - "status", - "runId" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the setup operation" - }, - "runId": { - "type": "string", - "description": "The Trigger.dev run ID for the setup-sandbox background task. Use this with [GET /api/tasks/runs](/api-reference/tasks/runs) to check the status and retrieve results.", - "example": "run_abc123def456" - } - } - }, - "DeleteSandboxRequest": { - "type": "object", - "properties": { - "account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the account to delete the sandbox for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, deletes the sandbox for the API key's own account." - } - } - }, - "DeleteSandboxResponse": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Status of the delete operation" - }, - "deleted_snapshot": { - "nullable": true, - "description": "The snapshot record that was deleted. Null if no snapshot existed for the account.", - "$ref": "#/components/schemas/UpdateSnapshotResponse" - }, - "error": { - "type": "string", - "description": "Error message (only present if status is error)" - } - } - }, - "UpdateSnapshotRequest": { - "type": "object", - "required": [], - "properties": { - "snapshotId": { - "type": "string", - "description": "The snapshot ID to set for the account. This snapshot will be used as the base environment when creating new sandboxes.", - "example": "snap_abc123def456" - }, - "github_repo": { - "type": "string", - "format": "uri", - "description": "The GitHub repository URL to associate with the account's sandbox environment. Must be a valid URL.", - "example": "https://github.com/org/repo" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the account to update the snapshot for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, updates the snapshot for the API key's own account." - } - } - }, - "UpdateSnapshotResponse": { - "type": "object", - "required": [ - "account_id", - "snapshot_id", - "expires_at", - "github_repo", - "created_at" - ], - "properties": { - "account_id": { - "type": "string", - "format": "uuid", - "description": "The account ID this snapshot belongs to", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "snapshot_id": { - "type": "string", - "description": "The snapshot ID that was set for the account", - "example": "snap_abc123def456" - }, - "expires_at": { - "type": "string", - "format": "date-time", - "description": "When the snapshot expires", - "example": "2027-01-01T00:00:00.000Z" - }, - "github_repo": { - "type": "string", - "nullable": true, - "description": "The GitHub repository URL associated with the sandbox", - "example": "https://github.com/org/repo" - }, - "created_at": { - "type": "string", - "format": "date-time", - "nullable": true, - "description": "When the snapshot record was created", - "example": "2025-01-01T00:00:00.000Z" - } - } - }, - "Pulse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "Unique identifier for the pulse" - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "Unique identifier for the associated account" - }, - "active": { - "type": "boolean", - "description": "Whether the pulse is active (defaults to true)" - } - } - }, - "PulseResponse": { - "type": "object", - "required": [ - "status", - "pulse" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Status of the request" - }, - "pulse": { - "$ref": "#/components/schemas/Pulse", - "description": "The pulse object" - }, - "error": { - "type": "string", - "description": "Error message (only present if status is error)" - } - } - }, - "PulsesResponse": { - "type": "object", - "required": [ - "status", - "pulses" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Status of the request" - }, - "pulses": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Pulse" - }, - "description": "Array of pulse objects. Contains pulses for the authenticated account. If the account has access to organizations, all organization accounts are included." - }, - "error": { - "type": "string", - "description": "Error message (only present if status is error)" - } - } - }, - "UpdatePulseRequest": { - "type": "object", - "required": [ - "active" - ], - "properties": { - "active": { - "type": "boolean", - "description": "Whether to enable or disable the pulse", - "example": true - }, - "account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the account to update the pulse for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, updates the pulse for the API key's own account." - } - } - }, - "TaskRunResponse": { - "type": "object", - "description": "Raw Trigger.dev SDK run object. The API passes through the SDK response without field mapping. See https://trigger.dev/docs/management/runs/retrieve for the full reference. When listing runs, `output`, `error`, `payload`, and `attempts` are not included.", - "required": [ - "id", - "status", - "taskIdentifier", - "createdAt", - "updatedAt" - ], - "properties": { - "id": { - "type": "string", - "description": "The unique run identifier, prefixed with `run_`" - }, - "status": { - "type": "string", - "enum": [ - "PENDING_VERSION", - "DELAYED", - "QUEUED", - "EXECUTING", - "REATTEMPTING", - "FROZEN", - "COMPLETED", - "CANCELED", - "FAILED", - "CRASHED", - "INTERRUPTED", - "SYSTEM_FAILURE" - ], - "description": "Current run status" - }, - "taskIdentifier": { - "type": "string", - "description": "The task type identifier (e.g. 'setup-sandbox', 'run-sandbox-command')" - }, - "idempotencyKey": { - "type": "string", - "nullable": true, - "description": "Idempotency key used to deduplicate trigger requests" - }, - "version": { - "type": "string", - "description": "The worker version that executed the run" - }, - "isTest": { - "type": "boolean", - "description": "Whether this is a test run" - }, - "createdAt": { - "type": "string", - "format": "date-time", - "description": "When the run was created (ISO 8601)" - }, - "updatedAt": { - "type": "string", - "format": "date-time", - "description": "When the run was last updated (ISO 8601)" - }, - "startedAt": { - "type": "string", - "format": "date-time", - "nullable": true, - "description": "When execution started (null if not yet started)" - }, - "finishedAt": { - "type": "string", - "format": "date-time", - "nullable": true, - "description": "When the run finished (null if still running)" - }, - "delayedUntil": { - "type": "string", - "format": "date-time", - "nullable": true, - "description": "If delayed, when the run becomes eligible to execute" - }, - "ttl": { - "description": "Time-to-live. If the run is not started within this duration, it expires.", - "nullable": true - }, - "expiredAt": { - "type": "string", - "format": "date-time", - "nullable": true, - "description": "When the run expired (null if not expired)" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Tags associated with this run (max 10)" - }, - "metadata": { - "type": "object", - "nullable": true, - "description": "JSON metadata attached to the run" - }, - "costInCents": { - "type": "number", - "description": "Compute cost of the run in cents" - }, - "baseCostInCents": { - "type": "number", - "description": "Base invocation cost in cents" - }, - "durationMs": { - "type": "number", - "description": "Compute duration in milliseconds" - }, - "env": { - "type": "object", - "description": "Environment the run executed in", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "user": { - "type": "string", - "nullable": true - } - } - }, - "depth": { - "type": "integer", - "description": "Nesting depth for child runs" - }, - "batchId": { - "type": "string", - "nullable": true, - "description": "Batch ID if triggered as part of a batch" - }, - "triggerFunction": { - "type": "string", - "enum": [ - "trigger", - "triggerAndWait", - "batchTrigger", - "batchTriggerAndWait" - ], - "description": "The function used to trigger this run" - }, - "payload": { - "description": "Input payload for the task. Only present when retrieving by runId.", - "nullable": true - }, - "output": { - "description": "Task output data. Only present when retrieving by runId.", - "nullable": true - }, - "error": { - "type": "object", - "nullable": true, - "description": "Error details if the run failed. Only present when retrieving by runId.", - "properties": { - "message": { - "type": "string", - "description": "Human-readable error message" - }, - "name": { - "type": "string", - "description": "Error name or type" - }, - "stackTrace": { - "type": "string", - "description": "Stack trace" - } - } - }, - "attempts": { - "type": "array", - "description": "Attempt history. Only present when retrieving by runId.", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Attempt ID, prefixed with `attempt_`" - }, - "status": { - "type": "string", - "enum": [ - "PENDING", - "EXECUTING", - "PAUSED", - "COMPLETED", - "FAILED", - "CANCELED" - ] - }, - "createdAt": { - "type": "string", - "format": "date-time" - }, - "updatedAt": { - "type": "string", - "format": "date-time" - }, - "startedAt": { - "type": "string", - "format": "date-time", - "nullable": true - }, - "completedAt": { - "type": "string", - "format": "date-time", - "nullable": true - }, - "error": { - "type": "object", - "nullable": true, - "properties": { - "message": { - "type": "string" - }, - "name": { - "type": "string" - }, - "stackTrace": { - "type": "string" - } - } - } - } - } - }, - "schedule": { - "type": "object", - "nullable": true, - "description": "Schedule information if triggered by a schedule. Only present when retrieving by runId." - }, - "relatedRuns": { - "type": "object", - "nullable": true, - "description": "Related run references (root, parent, children). Only present when retrieving by runId." - } - } - }, - "TaskRunListResponse": { - "type": "object", - "required": [ - "status", - "runs" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Indicates the request was successful" - }, - "runs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TaskRunResponse" - }, - "description": "List of recent task runs for the authenticated account. Each item is a raw Trigger.dev SDK run object (same shape as TaskRunResponse, but without `output` and `error` fields)." - } - } - }, - "FileTreeEntry": { - "type": "object", - "required": [ - "path", - "type", - "sha" - ], - "description": "A single entry in a GitHub repository file tree", - "properties": { - "path": { - "type": "string", - "description": "The file or directory path relative to the repository root", - "example": "src/index.ts" - }, - "type": { - "type": "string", - "enum": [ - "blob", - "tree" - ], - "description": "The type of entry: blob for files, tree for directories" - }, - "sha": { - "type": "string", - "description": "The SHA hash of the entry", - "example": "abc123def456" - }, - "size": { - "type": "integer", - "description": "The size of the file in bytes. Only present for blob entries.", - "example": 1024 - } - } - }, - "ContentCreateRequest": { - "type": "object", - "description": "Parameters for triggering the content creation pipeline.", - "properties": { - "artist_account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the artist account to create content for. Use [GET /api/artists](/api-reference/artists/list) to find artist account IDs.", - "example": "1873859c-dd37-4e9a-9bac-80d3558527a9" - }, - "template": { - "type": "string", - "description": "Optional template ID for content generation. Defines the visual style, scene, and prompt configuration. When omitted, the pipeline runs in malleable mode using only the params you provide. See GET /api/content/templates for available options.", - "example": "artist-caption-stage" - }, - "lipsync": { - "type": "boolean", - "description": "Whether to generate video with lip-synced audio. When `true`, uses an audio-to-video model that bakes audio into the video for lip movement. When `false`, generates video from the image alone and overlays audio in post. If omitted, the template's default workflow is used.", - "example": false - }, - "caption_length": { - "type": "string", - "enum": [ - "short", - "medium", - "long" - ], - "description": "Controls the length of the generated caption text. `short` produces 1-2 lines (punchy, minimal). `medium` produces 1-2 sentences. `long` produces a paragraph (stream of consciousness style). Defaults to `short`.", - "default": "short", - "example": "short" - }, - "upscale": { - "type": "boolean", - "description": "Whether to upscale the generated image and video for higher resolution and detail. Adds approximately 2 minutes to the pipeline. Defaults to `false`.", - "default": false, - "example": false - }, - "batch": { - "type": "integer", - "minimum": 1, - "maximum": 30, - "description": "Number of videos to generate in parallel. Each video independently selects a random reference image, song clip, and mood variation. The response always returns `runIds` as an array. Defaults to `1`.", - "default": 1, - "example": 1 - }, - "songs": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Optional list of song slugs or public URLs to use for the audio track. Song slugs match filenames without extension from the artist's `songs/` directory (e.g. `\"hiccups\"` for `hiccups.mp3`). Public URLs (e.g. `\"https://example.com/my-song.mp3\"`) are downloaded, transcribed, and clipped directly — bypassing the Git repo. When omitted, all songs in the artist's repo are eligible.", - "example": [ - "hiccups", - "https://example.com/unreleased-track.mp3" - ] - }, - "images": { - "type": "array", - "items": { - "type": "string", - "format": "uri" - }, - "description": "Optional list of public image URLs to use as face guides instead of the artist's default `face-guide.png` from their GitHub repo. The first image is used as the primary face guide. Useful when the caller wants to override the default face reference.", - "example": [ - "https://example.com/face.png" - ] - } - }, - "required": [ - "artist_account_id" - ] - }, - "ContentCreateResponse": { - "type": "object", - "required": [ - "runIds", - "status", - "artist_account_id" - ], - "description": "Confirmation that the content creation pipeline has been triggered. Always returns `runIds` as an array — even for a single run, it contains one element.", - "properties": { - "runIds": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Array of run IDs. Poll each via [GET /api/tasks/runs](/api-reference/tasks/runs). For single runs this contains one element.", - "example": [ - "run_abc123def456" - ] - }, - "status": { - "type": "string", - "enum": [ - "triggered" - ], - "description": "Indicates the pipeline has been triggered" - }, - "artist_account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the artist account the pipeline is running for", - "example": "1873859c-dd37-4e9a-9bac-80d3558527a9" - }, - "template": { - "type": [ - "string", - "null" - ], - "description": "Template ID when a preset pipeline is used; null in malleable mode.", - "example": null - }, - "lipsync": { - "type": "boolean", - "description": "Whether lip-sync mode is enabled", - "example": false - }, - "failed": { - "type": "integer", - "description": "Number of triggers that failed. Only present when some triggers failed.", - "example": 0 - } - } - }, - "ContentCreateErrorResponse": { - "type": "object", - "required": [ - "error" - ], - "description": "Returned when the artist is missing required files or the template is not found. Includes actionable instructions for resolving each issue.", - "properties": { - "error": { - "type": "string", - "description": "Human-readable error summary", - "example": "Artist 'new-artist' is not ready for content creation" - }, - "ready": { - "type": "boolean", - "description": "Always `false` when this error is returned", - "example": false - }, - "missing": { - "type": "array", - "description": "List of missing files with severity and fix instructions. Only present when the artist fails validation.", - "items": { - "$ref": "#/components/schemas/ContentMissingFile" - } - }, - "available_templates": { - "type": "array", - "description": "List of valid template names. Only present when the requested template was not found.", - "items": { - "type": "string" - }, - "example": [ - "artist-caption-bedroom", - "artist-caption-outside", - "artist-caption-stage" - ] - } - } - }, - "ContentErrorResponse": { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "type": "string", - "description": "Error message describing what went wrong", - "example": "Unauthorized" - } - } - }, - "ContentTemplatesResponse": { - "type": "object", - "required": [ - "templates" - ], - "description": "List of available content creation templates.", - "properties": { - "templates": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ContentTemplate" - } - } - } - }, - "ContentTemplate": { - "type": "object", - "required": [ - "id", - "description" - ], - "description": "A content creation template — a complete creative recipe defining visual style, composition, caption rules, and edit operations. Templates are optional; all primitives work without one.", - "properties": { - "id": { - "type": "string", - "description": "Template identifier. Pass this as the template field in content primitive requests or POST /api/content/create.", - "example": "artist-caption-bedroom" - }, - "description": { - "type": "string", - "description": "Human-readable description of the template's visual style", - "example": "Moody bedroom selfie. Artist on camera with deadpan expression, purple LED lighting, dark room. Short blunt captions in lowercase. Vertical 9:16 video, 8 seconds. Best for: introspective songs, vulnerable moments, daily content. Requires: face image, audio." - } - } - }, - "ContentTemplateDetail": { - "type": "object", - "required": [ - "id", - "description" - ], - "description": "Full configuration for a content creation template including image prompts, video motion config, caption style rules, and edit operations.", - "properties": { - "id": { - "type": "string", - "description": "Template identifier", - "example": "artist-caption-bedroom" - }, - "description": { - "type": "string", - "description": "Human-readable description of the template", - "example": "Moody bedroom selfie. Artist on camera with deadpan expression, purple LED lighting, dark room." - }, - "image": { - "type": "object", - "description": "Image generation configuration", - "properties": { - "prompt": { - "type": "string", - "description": "Default image prompt used when no caller prompt is provided" - }, - "reference_images": { - "type": "array", - "items": { - "type": "string", - "format": "uri" - }, - "description": "Reference image URLs for style conditioning" - }, - "style_rules": { - "type": "object", - "description": "Style constraints (lighting, colors, composition)" - } - } - }, - "video": { - "type": "object", - "description": "Video generation configuration", - "properties": { - "moods": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Mood descriptors for motion prompt generation" - }, - "movements": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Camera/subject movement descriptors" - } - } - }, - "caption": { - "type": "object", - "description": "Caption generation configuration", - "properties": { - "guide": { - "type": "object", - "description": "Caption style guide", - "properties": { - "tone": { - "type": "string", - "description": "Voice and tone direction" - }, - "rules": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Style rules for caption generation" - }, - "formats": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Allowed caption formats" - } - } - }, - "examples": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Example captions for few-shot prompting" - } - } - }, - "edit": { - "type": "object", - "description": "Post-processing edit operations", - "properties": { - "operations": { - "type": "array", - "description": "Default edit operations applied during post-processing", - "items": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "trim", - "crop", - "resize", - "overlay_text", - "mux_audio" - ], - "description": "Operation type" - }, - "start": { - "type": "number", - "description": "Start time in seconds (trim)" - }, - "duration": { - "type": "number", - "description": "Duration in seconds (trim)" - }, - "aspect": { - "type": "string", - "description": "Aspect ratio e.g. 9:16 (crop)" - }, - "width": { - "type": "integer", - "description": "Width in pixels (crop/resize)" - }, - "height": { - "type": "integer", - "description": "Height in pixels (crop/resize)" - }, - "content": { - "type": "string", - "description": "Text content (overlay_text)" - }, - "font": { - "type": "string", - "description": "Font name (overlay_text)" - }, - "color": { - "type": "string", - "description": "Text color (overlay_text)" - }, - "stroke_color": { - "type": "string", - "description": "Text stroke color (overlay_text)" - }, - "max_font_size": { - "type": "number", - "description": "Maximum font size (overlay_text)" - }, - "position": { - "type": "string", - "enum": [ - "top", - "center", - "bottom" - ], - "description": "Text position (overlay_text)" - }, - "audio_url": { - "type": "string", - "format": "uri", - "description": "Audio URL to mux (mux_audio)" - }, - "replace": { - "type": "boolean", - "description": "Replace existing audio (mux_audio)" - } - } - } - } - } - } - } - }, - "ContentValidateResponse": { - "type": "object", - "required": [ - "ready", - "artist_account_id" - ], - "description": "Validation report for an artist's content creation readiness.", - "properties": { - "ready": { - "type": "boolean", - "description": "`true` if the artist has all required files and the pipeline can run. `false` if required files are missing.", - "example": true - }, - "artist_account_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the artist account that was validated", - "example": "1873859c-dd37-4e9a-9bac-80d3558527a9" - }, - "songs": { - "type": "integer", - "description": "Number of songs found in the artist's `songs/` directory", - "example": 17 - }, - "templates": { - "type": "array", - "description": "Available templates that can be used with this artist", - "items": { - "type": "string" - }, - "example": [ - "artist-caption-bedroom", - "artist-caption-outside", - "artist-caption-stage" - ] - }, - "checks": { - "type": "object", - "description": "Per-file validation results. Only present when `ready` is `true`.", - "properties": { - "face_guide": { - "$ref": "#/components/schemas/ContentValidationCheck" - }, - "artist_context": { - "$ref": "#/components/schemas/ContentValidationCheck" - }, - "audience_context": { - "$ref": "#/components/schemas/ContentValidationCheck" - }, - "songs": { - "allOf": [ - { - "$ref": "#/components/schemas/ContentValidationCheck" - }, - { - "type": "object", - "properties": { - "count": { - "type": "integer", - "description": "Number of songs found", - "example": 17 - } - } - } - ] - } - } - }, - "missing": { - "type": "array", - "description": "List of missing files with severity and fix instructions. Only present when `ready` is `false`.", - "items": { - "$ref": "#/components/schemas/ContentMissingFile" - } - } - } - }, - "ContentValidationCheck": { - "type": "object", - "required": [ - "status" - ], - "description": "Status of a single validation check.", - "properties": { - "status": { - "type": "string", - "enum": [ - "ok", - "missing", - "warning" - ], - "description": "Whether the file was found", - "example": "ok" - } - } - }, - "ContentMissingFile": { - "type": "object", - "required": [ - "file", - "severity", - "description", - "fix" - ], - "description": "A missing file that prevents or degrades content creation.", - "properties": { - "file": { - "type": "string", - "description": "Relative path of the missing file within the artist directory", - "example": "context/images/face-guide.png" - }, - "severity": { - "type": "string", - "enum": [ - "required", - "recommended" - ], - "description": "`required` means the pipeline will fail without this file. `recommended` means the pipeline will run but output quality is degraded.", - "example": "required" - }, - "description": { - "type": "string", - "description": "What this file is used for in the pipeline", - "example": "Face guide image used for AI image generation" - }, - "fix": { - "type": "string", - "description": "Actionable instructions for creating or adding the missing file", - "example": "Generate a face guide using fal-ai/nano-banana-pro/edit with 2-3 reference photos of the artist" - } - } - }, - "ContentEstimateResponse": { - "type": "object", - "required": [ - "workflows" - ], - "description": "Cost estimates based on current pricing. When `compare` is `false`, the `workflows` array contains a single entry. When `true`, it contains all available profiles.", - "properties": { - "workflows": { - "type": "array", - "description": "One or more workflow cost breakdowns", - "items": { - "$ref": "#/components/schemas/ContentWorkflowEstimate" - } - }, - "comparison": { - "description": "Side-by-side summary. Only present when `compare` is `true` and multiple workflows are returned.", - "$ref": "#/components/schemas/ContentEstimateComparison" - }, - "batch": { - "type": "object", - "description": "Batch cost projection. Only present when `batch` > 1.", - "properties": { - "count": { - "type": "integer", - "description": "Number of videos in the batch", - "example": 30 - }, - "cheapestTotal": { - "type": "number", - "format": "float", - "description": "Total cost for the batch using the cheapest workflow", - "example": 5.4 - }, - "mostExpensiveTotal": { - "type": "number", - "format": "float", - "description": "Total cost for the batch using the most expensive workflow", - "example": 28.5 - } - } - } - } - }, - "ContentWorkflowEstimate": { - "type": "object", - "required": [ - "name", - "perVideo", - "steps" - ], - "description": "Cost breakdown for a single workflow profile.", - "properties": { - "name": { - "type": "string", - "description": "Workflow profile name", - "example": "Current (image-to-video)" - }, - "perVideo": { - "type": "number", - "format": "float", - "description": "Total estimated cost per video in USD", - "example": 0.82 - }, - "steps": { - "type": "array", - "description": "Per-step cost breakdown showing where the money goes", - "items": { - "$ref": "#/components/schemas/ContentStepEstimate" - } - }, - "costBreakdown": { - "type": "object", - "description": "Summary of the biggest cost driver", - "properties": { - "mostExpensiveStep": { - "type": "string", - "description": "Name of the step that costs the most", - "example": "Generate Video" - }, - "mostExpensivePercent": { - "type": "integer", - "description": "Percentage of total cost from the most expensive step", - "example": 68 - } - } - } - } - }, - "ContentStepEstimate": { - "type": "object", - "required": [ - "name", - "model", - "cost", - "note" - ], - "description": "Cost details for a single pipeline step.", - "properties": { - "name": { - "type": "string", - "description": "Pipeline step name", - "example": "Generate Image" - }, - "model": { - "type": "string", - "description": "The AI model or service used for this step", - "example": "fal-ai/nano-banana-pro/edit" - }, - "cost": { - "type": "number", - "format": "float", - "description": "Estimated cost for this step in USD", - "example": 0.04 - }, - "unit": { - "type": "string", - "description": "Billing unit type (e.g., `images`, `seconds`, `megapixels`). Not present for free steps.", - "example": "images" - }, - "unitPrice": { - "type": "number", - "format": "float", - "description": "Price per billing unit in USD. Not present for free steps.", - "example": 0.04 - }, - "note": { - "type": "string", - "description": "Human-readable calculation detail", - "example": "1 call" - } - } - }, - "ContentEstimateComparison": { - "type": "object", - "required": [ - "cheapest", - "cheapestPerVideo", - "mostExpensive", - "mostExpensivePerVideo", - "savingsPercent" - ], - "description": "Summary comparing the cheapest and most expensive workflow options.", - "properties": { - "cheapest": { - "type": "string", - "description": "Name of the cheapest workflow profile", - "example": "Budget (no upscale, LTX video)" - }, - "cheapestPerVideo": { - "type": "number", - "format": "float", - "description": "Cost per video for the cheapest workflow", - "example": 0.18 - }, - "mostExpensive": { - "type": "string", - "description": "Name of the most expensive workflow profile", - "example": "Current (audio-to-video)" - }, - "mostExpensivePerVideo": { - "type": "number", - "format": "float", - "description": "Cost per video for the most expensive workflow", - "example": 0.95 - }, - "savingsPercent": { - "type": "integer", - "description": "Percentage savings between the cheapest and most expensive workflows", - "example": 81 - } - } - }, - "SongAnalyzeRequest": { - "type": "object", - "description": "Provide exactly one of `preset` or `prompt`. Use `preset` for structured analysis workflows, or `prompt` for free-form questions.", - "properties": { - "preset": { - "type": "string", - "enum": [ - "catalog_metadata", - "mood_tags", - "lyric_transcription", - "mix_feedback", - "song_description", - "music_theory", - "similar_artists", - "sample_detection", - "sync_brief_match", - "audience_profile", - "content_advisory", - "playlist_pitch", - "artist_development_notes", - "full_report" - ], - "description": "Name of a curated analysis preset. Use instead of prompt for structured, optimized output. The 'full_report' preset runs all 13 presets in parallel and returns a comprehensive report. See [List Analyze Presets](/api-reference/songs/analyze-presets) for the full list of available presets.", - "example": "catalog_metadata" - }, - "prompt": { - "type": "string", - "minLength": 1, - "maxLength": 24000, - "description": "Text prompt or question about the music", - "example": "Describe the genre, tempo, and mood of this track." - }, - "audio_url": { - "type": "string", - "format": "uri", - "description": "Public URL to an audio file (MP3, WAV, or FLAC — up to 20 minutes)", - "example": "https://example.com/song.mp3" - }, - "max_new_tokens": { - "type": "integer", - "minimum": 1, - "maximum": 2048, - "default": 512, - "description": "Maximum number of tokens to generate", - "example": 512 - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2, - "default": 1, - "description": "Controls output creativity — higher values produce more varied responses", - "example": 0.7 - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1, - "default": 1, - "description": "Nucleus sampling probability cutoff", - "example": 0.9 - }, - "do_sample": { - "type": "boolean", - "default": false, - "description": "Enable sampling (set true when using temperature or top_p)", - "example": false - } - } - }, - "SongAnalyzeResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Request status" - }, - "preset": { - "type": "string", - "description": "Preset used for analysis, when applicable", - "example": "catalog_metadata" - }, - "response": { - "description": "Model output for single-preset or custom-prompt analysis. May be plain text or structured JSON depending on the preset." - }, - "report": { - "type": "object", - "description": "Full report payload returned only when using the `full_report` preset" - }, - "elapsed_seconds": { - "type": "number", - "format": "float", - "description": "Inference time in seconds" - } - } - }, - "SongAnalyzeErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "error" - ], - "description": "Error status" - }, - "missing_fields": { - "type": "array", - "description": "Path to the first invalid or missing field when validation fails", - "items": { - "type": "string" - } - }, - "error": { - "type": "string", - "description": "Error message describing what went wrong" - } - } - }, - "CheckAdminResponse": { - "type": "object", - "required": [ - "status", - "isAdmin" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "success" - ], - "description": "Status of the request" - }, - "isAdmin": { - "type": "boolean", - "description": "Whether the authenticated account is a Recoup admin" - } - } - }, - "AccountSandboxRow": { - "type": "object", - "required": [ - "account_id", - "total_sandboxes", - "last_created_at" - ], - "properties": { - "account_id": { - "type": "string", - "format": "uuid", - "description": "The unique identifier of the account", - "example": "04e3aba9-c130-4fb8-8b92-34e95d43e66b" - }, - "total_sandboxes": { - "type": "integer", - "description": "Total number of sandboxes created for this account", - "example": 5 - }, - "last_created_at": { - "type": "string", - "format": "date-time", - "description": "ISO 8601 timestamp of the most recently created sandbox for this account", - "example": "2026-03-10T12:00:00Z" - }, - "account_email": { - "type": "string", - "nullable": true, - "description": "The email address of the account. Null if the account has no email set.", - "example": "alice@example.com" - } - }, - "description": "" - }, - "AdminSandboxesResponse": { - "type": "object", - "required": [ - "status", - "accounts" - ], - "description": "Response containing per-account sandbox statistics for admin use", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Status of the request" - }, - "accounts": { - "type": "array", - "description": "List of accounts with their sandbox statistics, ordered by most recently active first", - "items": { - "$ref": "#/components/schemas/AccountSandboxRow" - } - } - } - }, - "OrgRepoRow": { - "type": "object", - "required": [ - "repo_name", - "repo_url", - "total_commits", - "latest_commit_messages", - "earliest_committed_at", - "latest_committed_at", - "account_repos" - ], - "description": "Commit statistics for a single GitHub org repository", - "properties": { - "repo_name": { - "type": "string", - "description": "Repository name", - "example": "chat" - }, - "repo_url": { - "type": "string", - "description": "Full GitHub HTML URL of the repository", - "example": "https://github.com/recoupable/chat" - }, - "total_commits": { - "type": "integer", - "description": "Total number of commits in the repository", - "example": 5696 - }, - "latest_commit_messages": { - "type": "array", - "description": "Messages from the 5 most recent commits", - "items": { - "type": "string" - }, - "example": [ - "Merge test into main", - "fix: duration stuck at 0ms for in-progress tasks" - ] - }, - "earliest_committed_at": { - "type": "string", - "format": "date-time", - "description": "ISO 8601 timestamp of the earliest (first) commit", - "example": "2024-09-27T17:16:01Z" - }, - "latest_committed_at": { - "type": "string", - "format": "date-time", - "description": "ISO 8601 timestamp of the most recent commit", - "example": "2026-03-10T19:57:37Z" - }, - "account_repos": { - "type": "array", - "items": { - "type": "object", - "properties": { - "account_id": { - "type": "string" - }, - "email": { - "type": "string", - "nullable": true - }, - "repo_url": { - "type": "string" - } - }, - "required": [ - "account_id", - "repo_url" - ] - }, - "description": "List of accounts using this org repo as a submodule, with account_id, email, and repo_url" - } - } - }, - "AdminEmailsResponse": { - "type": "object", - "required": [ - "status", - "emails" - ], - "description": "Response containing Resend emails sent for an account", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Status of the request" - }, - "emails": { - "type": "array", - "description": "List of emails sent for the account, ordered by created_at descending", - "items": { - "$ref": "#/components/schemas/PulseEmailRow" - } - } - } - }, - "PulseEmailRow": { - "type": "object", - "required": [ - "id", - "from", - "to", - "subject", - "created_at", - "last_event" - ], - "description": "A single email record from Resend (full GetEmailResponseSuccess). See [Resend API docs](https://resend.com/docs/api-reference/emails/retrieve-email) for the source of truth.", - "properties": { - "id": { - "type": "string", - "description": "The Resend email ID" - }, - "from": { - "type": "string", - "description": "Sender email address" - }, - "to": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Recipient email addresses" - }, - "cc": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "description": "CC recipient email addresses" - }, - "bcc": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "description": "BCC recipient email addresses" - }, - "reply_to": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "description": "Reply-to email addresses" - }, - "subject": { - "type": "string", - "description": "Email subject line" - }, - "html": { - "type": "string", - "nullable": true, - "description": "HTML content of the email" - }, - "text": { - "type": "string", - "nullable": true, - "description": "Plain text content of the email" - }, - "created_at": { - "type": "string", - "format": "date-time", - "description": "Timestamp when the email was created" - }, - "scheduled_at": { - "type": "string", - "format": "date-time", - "nullable": true, - "description": "Scheduled send time, if any" - }, - "last_event": { - "type": "string", - "enum": [ - "bounced", - "canceled", - "clicked", - "complained", - "delivered", - "delivery_delayed", - "failed", - "opened", - "queued", - "scheduled", - "sent" - ], - "description": "Most recent delivery event for this email" - }, - "tags": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "name", - "value" - ] - }, - "nullable": true, - "description": "Custom tags attached to the email" - } - } - }, - "AdminSandboxOrgsResponse": { - "type": "object", - "required": [ - "status", - "repos" - ], - "description": "Response containing commit statistics for all org repositories", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Status of the request" - }, - "repos": { - "type": "array", - "description": "List of org repos with their commit statistics, ordered by total_commits descending", - "items": { - "$ref": "#/components/schemas/OrgRepoRow" - } - } - } - }, - "ContentCreateImageRequest": { - "type": "object", - "properties": { - "template": { - "type": "string", - "description": "Optional template ID. When provided, uses the template's image prompt, reference images, and style rules. Caller params override template defaults. Artist context overrides template style when available. See [GET /api/content/templates](/api-reference/content/templates) for available options." - }, - "prompt": { - "type": "string", - "description": "Optional prompt to guide image generation" - }, - "reference_image_url": { - "type": "string", - "format": "uri", - "description": "URL of a reference image for conditioning the generation" - }, - "images": { - "type": "array", - "items": { - "type": "string", - "format": "uri" - }, - "description": "Optional reference image URLs to guide generation" - }, - "model": { - "type": "string", - "description": "fal.ai model ID. Defaults to fal-ai/nano-banana-pro/edit" - } - } - }, - "ContentCreateImageResponse": { - "type": "object", - "required": [ - "imageUrl" - ], - "properties": { - "imageUrl": { - "type": "string", - "format": "uri", - "description": "URL of the generated image" - } - } - }, - "ContentCreateVideoRequest": { - "type": "object", - "properties": { - "template": { - "type": "string", - "description": "Optional template ID. When provided, the template's video config (moods, movements) is used as the motion prompt. Caller params override template defaults. See [GET /api/content/templates](/api-reference/content/templates) for available options." - }, - "mode": { - "type": "string", - "enum": [ - "prompt", - "animate", - "reference", - "extend", - "first-last", - "lipsync" - ], - "description": "What kind of video to generate. If omitted, inferred from the inputs you provide." - }, - "prompt": { - "type": "string", - "description": "Text describing the video content, motion, or how to continue/extend" - }, - "image_url": { - "type": "string", - "format": "uri", - "description": "Image URL. Used as the first frame (animate), style reference (reference), start frame (first-last), or face source (lipsync)" - }, - "end_image_url": { - "type": "string", - "format": "uri", - "description": "End frame image URL. Only used with `first-last` mode" - }, - "video_url": { - "type": "string", - "format": "uri", - "description": "Video URL to extend. Only used with `extend` mode (max 8 seconds input)" - }, - "audio_url": { - "type": "string", - "format": "uri", - "description": "Audio URL for lipsync mode. The generated face will move in sync with this audio" - }, - "aspect_ratio": { - "type": "string", - "enum": [ - "auto", - "16:9", - "9:16" - ], - "default": "auto", - "description": "Aspect ratio of the output video" - }, - "duration": { - "type": "string", - "enum": [ - "4s", - "6s", - "7s", - "8s" - ], - "default": "8s", - "description": "Duration of the generated video" - }, - "resolution": { - "type": "string", - "enum": [ - "720p", - "1080p", - "4k" - ], - "default": "720p", - "description": "Output resolution" - }, - "negative_prompt": { - "type": "string", - "description": "Describe what you do NOT want in the video" - }, - "generate_audio": { - "type": "boolean", - "default": false, - "description": "Generate audio for the video" - }, - "model": { - "type": "string", - "description": "Override the model. Auto-selected based on mode if omitted" - } - } - }, - "ContentCreateVideoResponse": { - "type": "object", - "required": [ - "videoUrl" - ], - "properties": { - "videoUrl": { - "type": "string", - "format": "uri", - "description": "URL of the generated video" - } - } - }, - "ContentCreateTextRequest": { - "type": "object", - "required": [ - "topic" - ], - "properties": { - "template": { - "type": "string", - "description": "Optional template ID. When provided, injects the template's caption guide (tone, rules, formats) and examples into the LLM prompt. Caller's topic is still required. See [GET /api/content/templates](/api-reference/content/templates) for available options." - }, - "topic": { - "type": "string", - "description": "The subject or theme for caption generation" - }, - "length": { - "type": "string", - "enum": [ - "short", - "medium", - "long" - ], - "default": "short", - "description": "Desired text length" - } - } - }, - "ContentCreateTextResponse": { - "type": "object", - "required": [ - "content", - "color", - "borderColor", - "maxFontSize" - ], - "properties": { - "content": { - "type": "string", - "description": "Generated on-screen text content" - }, - "font": { - "type": [ - "string", - "null" - ], - "description": "Font name for the text, or null for default" - }, - "color": { - "type": "string", - "description": "Text color as a CSS color value", - "example": "#FFFFFF" - }, - "borderColor": { - "type": "string", - "description": "Text border/stroke color as a CSS color value", - "example": "#000000" - }, - "maxFontSize": { - "type": "number", - "description": "Maximum font size in pixels", - "example": 48 - } - } - }, - "ContentCreateAudioSegment": { - "type": "object", - "required": [ - "start", - "end", - "text" - ], - "properties": { - "start": { - "type": "number", - "description": "Segment start time in seconds" - }, - "end": { - "type": "number", - "description": "Segment end time in seconds" - }, - "text": { - "type": "string", - "description": "Transcribed text for this segment" - } - } - }, - "ContentCreateAudioRequest": { - "type": "object", - "required": [ - "audio_urls" - ], - "properties": { - "audio_urls": { - "type": "array", - "items": { - "type": "string", - "format": "uri" - }, - "minItems": 1, - "description": "Audio file URLs to transcribe" - }, - "model": { - "type": "string", - "description": "fal.ai model ID. Defaults to fal-ai/whisper" - } - } - }, - "ContentCreateAudioResponse": { - "type": "object", - "required": [ - "songUrl", - "fullLyrics", - "segments", - "segmentCount" - ], - "properties": { - "songUrl": { - "type": "string", - "description": "URL of the transcribed song" - }, - "fullLyrics": { - "type": "string", - "description": "Complete transcribed lyrics as a single string" - }, - "segments": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ContentCreateAudioSegment" - }, - "description": "Timestamped lyric segments" - }, - "segmentCount": { - "type": "number", - "description": "Total number of segments returned" - } - } - }, - "ContentCreateEditRequest": { - "type": "object", - "description": "Must provide at least one input (video_url, image_url, or audio_url)", - "properties": { - "video_url": { - "type": "string", - "format": "uri", - "description": "Input video URL" - }, - "image_url": { - "type": "string", - "format": "uri", - "description": "Input image URL" - }, - "audio_url": { - "type": "string", - "format": "uri", - "description": "Input audio URL" - }, - "template": { - "type": "string", - "description": "Template name for deterministic edit config. If provided, operations are read from the template. See [GET /api/content/templates](/api-reference/content/templates) for available options." - }, - "operations": { - "type": "array", - "description": "Array of edit operations to apply in order. Required if template is not provided.", - "items": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "trim", - "crop", - "resize", - "overlay_text", - "mux_audio" - ], - "description": "Operation type" - }, - "start": { - "type": "number", - "description": "Start time in seconds (trim)" - }, - "duration": { - "type": "number", - "description": "Duration in seconds (trim)" - }, - "aspect": { - "type": "string", - "description": "Aspect ratio e.g. 9:16 (crop)" - }, - "width": { - "type": "integer", - "description": "Width in pixels (crop/resize)" - }, - "height": { - "type": "integer", - "description": "Height in pixels (crop/resize)" - }, - "content": { - "type": "string", - "description": "Text content (overlay_text)" - }, - "font": { - "type": "string", - "description": "Font name (overlay_text)" - }, - "color": { - "type": "string", - "description": "Text color (overlay_text)" - }, - "stroke_color": { - "type": "string", - "description": "Text stroke color (overlay_text)" - }, - "max_font_size": { - "type": "number", - "description": "Maximum font size (overlay_text)" - }, - "position": { - "type": "string", - "enum": [ - "top", - "center", - "bottom" - ], - "description": "Text position (overlay_text)" - }, - "audio_url": { - "type": "string", - "format": "uri", - "description": "Audio URL to mux (mux_audio)" - }, - "replace": { - "type": "boolean", - "description": "Replace existing audio (mux_audio)" - } - } - } - }, - "output_format": { - "type": "string", - "enum": [ - "mp4", - "webm", - "mov" - ], - "default": "mp4", - "description": "Output format" - } - } - }, - "ContentCreateEditResponse": { - "type": "object", - "required": [ - "runId", - "status" - ], - "properties": { - "runId": { - "type": "string", - "description": "Background task run ID. Poll via [GET /api/tasks/runs](/api-reference/tasks/runs) to check progress." - }, - "status": { - "type": "string", - "enum": [ - "triggered" - ], - "description": "Status of the edit task" - } - } - }, - "ContentCreateUpscaleRequest": { - "type": "object", - "required": [ - "url", - "type" - ], - "properties": { - "url": { - "type": "string", - "format": "uri", - "description": "URL of the image or video to upscale" - }, - "type": { - "type": "string", - "enum": [ - "image", - "video" - ], - "description": "Whether the input is an image or video" - } - } - }, - "ContentCreateUpscaleResponse": { - "type": "object", - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string", - "format": "uri", - "description": "URL of the upscaled image or video" - } - } - }, - "ContentCreateAnalyzeRequest": { - "type": "object", - "required": [ - "video_url", - "prompt" - ], - "properties": { - "video_url": { - "type": "string", - "format": "uri", - "description": "Publicly accessible URL of the video to analyze. Supported formats: MP4, MOV, AVI, and other FFmpeg-compatible formats. Maximum duration: 1 hour." - }, - "prompt": { - "type": "string", - "maxLength": 2000, - "description": "A text prompt that guides the analysis. Can be instructive, descriptive, or phrased as a question. Examples: \"Describe the key moments in this video\", \"Generate 5 SEO keywords for this video\"." - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 1, - "default": 0.2, - "description": "Controls the randomness of the text output. Lower values produce more focused results. Defaults to `0.2`." - }, - "max_tokens": { - "type": "integer", - "minimum": 1, - "maximum": 4096, - "description": "Maximum number of tokens to generate. If omitted, uses the model default." - } - } - }, - "ContentCreateAnalyzeResponse": { - "type": "object", - "required": [ - "text" - ], - "properties": { - "text": { - "type": "string", - "description": "The generated analysis text based on the video and prompt." - }, - "finish_reason": { - "type": "string", - "enum": [ - "stop", - "length" - ], - "nullable": true, - "description": "`stop` if the generation completed normally. `length` if truncated at the token limit." - }, - "usage": { - "type": "object", - "nullable": true, - "properties": { - "output_tokens": { - "type": "integer", - "description": "Number of tokens in the generated text." - } - } - } - } - }, - "ResearchAlbum": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "release_date": { - "type": "string", - "nullable": true - } - }, - "additionalProperties": true - }, - "ResearchAlbumsResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "albums": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResearchAlbum" - } - } - } - }, - "ResearchAudienceResponse": { - "type": "object", - "description": "Audience demographics breakdown — age ranges, gender split, and country distribution for the specified platform.", - "properties": { - "status": { - "type": "string" - }, - "age": { - "type": "array", - "description": "Age range breakdown", - "items": { - "type": "object", - "additionalProperties": true - } - }, - "gender": { - "type": "object", - "description": "Gender split percentages", - "additionalProperties": true - }, - "countries": { - "type": "array", - "description": "Top countries by audience share", - "items": { - "type": "object", - "additionalProperties": true - } - } - }, - "additionalProperties": true - }, - "ResearchCareerResponse": { - "type": "object", - "description": "Career timeline — milestones, trajectory, and career stage history.", - "properties": { - "status": { - "type": "string" - }, - "career_stage": { - "type": "string", - "description": "Current career stage (e.g., 'Mid-Level', 'Superstar')" - }, - "data": { - "type": "array", - "description": "Career timeline data points", - "items": { - "type": "object", - "additionalProperties": true - } - } - }, - "additionalProperties": true - }, - "ResearchChartsResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "data": { - "type": "object", - "description": "Chart data — structure varies by platform.", - "additionalProperties": true - } - } - }, - "ResearchCitiesEntry": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "City name." - }, - "country": { - "type": "string", - "description": "ISO country code." - }, - "listeners": { - "type": "integer", - "description": "Listener count in this city." - } - } - }, - "ResearchCitiesResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "cities": { - "type": "array", - "description": "Cities ranked by listener concentration.", - "items": { - "$ref": "#/components/schemas/ResearchCitiesEntry" - } - } - } - }, - "ResearchCuratorResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "name": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "image_url": { - "type": "string", - "format": "uri", - "nullable": true - }, - "num_playlists": { - "type": "integer", - "nullable": true - }, - "followers": { - "type": "integer", - "nullable": true - } - }, - "additionalProperties": true - }, - "ResearchDeepRequest": { - "type": "object", - "required": [ - "query" - ], - "description": "Request body for deep research. Performs comprehensive multi-source analysis.", - "properties": { - "query": { - "type": "string", - "description": "The research question — be specific and detailed for best results." - } - } - }, - "ResearchDeepResponse": { - "type": "object", - "description": "Comprehensive research report with citations.", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "content": { - "type": "string", - "description": "The full research report as markdown." - }, - "citations": { - "type": "array", - "description": "Source URLs cited in the report.", - "items": { - "type": "string", - "format": "uri" - } - } - } - }, - "ResearchDiscoverArtist": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "sp_monthly_listeners": { - "type": "integer", - "nullable": true - }, - "sp_followers": { - "type": "integer", - "nullable": true - }, - "tiktok_followers": { - "type": "integer", - "nullable": true - }, - "ins_followers": { - "type": "integer", - "nullable": true - }, - "country": { - "type": "string", - "nullable": true, - "description": "ISO country code." - } - }, - "additionalProperties": true - }, - "ResearchDiscoverResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "artists": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResearchDiscoverArtist" - } - } - } - }, - "ResearchEnrichRequest": { - "type": "object", - "required": [ - "input", - "schema" - ], - "properties": { - "input": { - "type": "string", - "description": "What to research (e.g., \"Drake rapper from Dallas Texas\")." - }, - "schema": { - "type": "object", - "description": "JSON schema defining the fields to extract.", - "additionalProperties": true - }, - "processor": { - "type": "string", - "enum": [ - "base", - "core", - "ultra" - ], - "default": "base", - "description": "Research depth: base (fast), core (balanced), ultra (comprehensive)." - } - } - }, - "ResearchEnrichResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "output": { - "type": "object", - "description": "Structured data matching the provided schema.", - "additionalProperties": true - }, - "research_basis": { - "type": "object", - "properties": { - "citations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "url": { - "type": "string", - "format": "uri" - }, - "title": { - "type": "string" - }, - "field": { - "type": "string", - "description": "Which output field this citation supports." - } - } - } - } - } - } - } - }, - "ResearchExtractRequest": { - "type": "object", - "required": [ - "urls" - ], - "properties": { - "urls": { - "type": "array", - "items": { - "type": "string", - "format": "uri" - }, - "maxItems": 10, - "description": "URLs to extract content from (max 10)." - }, - "objective": { - "type": "string", - "description": "What information to focus on (optional, max 3000 chars)." - }, - "full_content": { - "type": "boolean", - "default": false, - "description": "Return full page content instead of focused excerpts." - } - } - }, - "ResearchExtractResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResearchExtractResult" - } - }, - "errors": { - "type": "array", - "items": { - "type": "object" - }, - "description": "URLs that failed to extract." - } - } - }, - "ResearchExtractResult": { - "type": "object", - "properties": { - "url": { - "type": "string", - "format": "uri" - }, - "title": { - "type": "string", - "nullable": true - }, - "publish_date": { - "type": "string", - "nullable": true, - "description": "Publish date in YYYY-MM-DD format." - }, - "excerpts": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "description": "Focused excerpts as markdown." - }, - "full_content": { - "type": "string", - "nullable": true, - "description": "Full page content as markdown." - } - } - }, - "ResearchFestival": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "city": { - "type": "string", - "nullable": true - }, - "country": { - "type": "string", - "nullable": true - } - }, - "additionalProperties": true - }, - "ResearchFestivalsResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "festivals": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResearchFestival" - } - } - } - }, - "ResearchGenre": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "id": { - "type": "integer" - } - } - }, - "ResearchGenresResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "genres": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResearchGenre" - } - } - } - }, - "ResearchInsight": { - "type": "object", - "properties": { - "text": { - "type": "string", - "description": "The insight text." - } - }, - "additionalProperties": true - }, - "ResearchInsightsResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "insights": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResearchInsight" - } - } - } - }, - "ResearchInstagramPostsResponse": { - "type": "object", - "description": "Top Instagram posts and reels sorted by engagement.", - "properties": { - "status": { - "type": "string" - }, - "posts": { - "type": "array", - "items": { - "type": "object", - "properties": { - "url": { - "type": "string" - }, - "likes": { - "type": "integer" - }, - "comments": { - "type": "integer" - }, - "timestamp": { - "type": "string" - } - }, - "additionalProperties": true - } - } - }, - "additionalProperties": true - }, - "ResearchLookupResponse": { - "type": "object", - "description": "Artist profile resolved from a platform URL or ID.", - "properties": { - "status": { - "type": "string" - }, - "id": { - "type": "integer", - "description": "Chartmetric artist ID" - }, - "spotify_id": { - "type": "string" - }, - "apple_music_id": { - "type": "string" - }, - "deezer_id": { - "type": "string" - } - }, - "additionalProperties": true - }, - "ResearchMetricsResponse": { - "type": "object", - "description": "Time-series metrics for a specific platform. Shape varies by source — typically an array of data points with timestamps and values (followers, listeners, views, etc.).", - "properties": { - "status": { - "type": "string" - }, - "data": { - "type": "array", - "description": "Array of time-series data points. Fields vary by platform.", - "items": { - "type": "object", - "additionalProperties": true - } - } - }, - "additionalProperties": true - }, - "ResearchMilestone": { - "type": "object", - "properties": { - "date": { - "type": "string", - "description": "Date of the milestone event." - }, - "summary": { - "type": "string", - "description": "Human-readable description of the event." - }, - "platform": { - "type": "string", - "description": "Platform where the event occurred (e.g. spotify, apple_music)." - }, - "track_name": { - "type": "string", - "description": "Name of the track involved, if any." - }, - "stars": { - "type": "integer", - "description": "Importance rating (1-5 stars)." - } - } - }, - "ResearchMilestonesResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "milestones": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResearchMilestone" - } - } - } - }, - "ResearchPeopleRequest": { - "type": "object", - "required": [ - "query" - ], - "properties": { - "query": { - "type": "string", - "description": "Natural language search for people (e.g., \"A&R reps at Atlantic Records\")." - }, - "num_results": { - "type": "integer", - "minimum": 1, - "maximum": 100, - "default": 10, - "description": "Number of results to return." - } - } - }, - "ResearchPeopleResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResearchPeopleResult" - } - } - } - }, - "ResearchPeopleResult": { - "type": "object", - "properties": { - "title": { - "type": "string", - "description": "Person name and role." - }, - "url": { - "type": "string", - "format": "uri", - "description": "Profile URL (often LinkedIn)." - }, - "highlights": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Key excerpts from the profile." - }, - "summary": { - "type": "string", - "nullable": true, - "description": "Brief summary of the person." - } - } - }, - "ResearchPlaylistPlacement": { - "type": "object", - "properties": { - "playlist_name": { - "type": "string" - }, - "track_name": { - "type": "string" - }, - "position": { - "type": "integer", - "nullable": true - }, - "peak_position": { - "type": "integer", - "nullable": true - }, - "followers": { - "type": "integer", - "nullable": true, - "description": "Playlist follower count." - }, - "added_at": { - "type": "string", - "nullable": true, - "description": "When the track was added." - }, - "removed_at": { - "type": "string", - "nullable": true, - "description": "When the track was removed (past placements only)." - }, - "curator_name": { - "type": "string", - "nullable": true - } - }, - "additionalProperties": true - }, - "ResearchPlaylistResponse": { - "type": "object", - "description": "Playlist metadata — name, description, follower count, track count, and curator info.", - "properties": { - "status": { - "type": "string" - }, - "name": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "description": { - "type": "string" - }, - "followers": { - "type": "integer" - }, - "num_tracks": { - "type": "integer" - }, - "curator_name": { - "type": "string" - } - }, - "additionalProperties": true - }, - "ResearchPlaylistsResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "placements": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResearchPlaylistPlacement" - } - } - } - }, - "ResearchProfileResponse": { - "type": "object", - "description": "Full artist profile — bio, genres, social links, label, images, and basic stats.", - "properties": { - "status": { - "type": "string" - }, - "name": { - "type": "string" - }, - "id": { - "type": "integer", - "description": "Chartmetric artist ID" - }, - "image_url": { - "type": "string" - }, - "genres": { - "type": "array", - "items": { - "type": "string" - } - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "description": { - "type": "string" - }, - "hometown": { - "type": "string" - }, - "record_label": { - "type": "string" - }, - "sp_followers": { - "type": "integer" - }, - "sp_monthly_listeners": { - "type": "integer" - } - }, - "additionalProperties": true - }, - "ResearchRadioResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "stations": { - "type": "array", - "description": "Radio stations tracked by Chartmetric.", - "items": { - "type": "object", - "additionalProperties": true - } - } - } - }, - "ResearchRankResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "rank": { - "type": "integer", - "nullable": true, - "description": "Global Chartmetric artist rank." - } - } - }, - "ResearchSearchResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "results": { - "type": "array", - "description": "Matching artists with IDs, names, and basic metadata.", - "items": { - "$ref": "#/components/schemas/ResearchSearchResult" - } - } - } - }, - "ResearchSearchResult": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "id": { - "type": "integer", - "description": "Internal ID for use with other research endpoints." - }, - "spotify_id": { - "type": "string", - "nullable": true - } - }, - "additionalProperties": true - }, - "ResearchSimilarArtist": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "similarity": { - "type": "number", - "description": "Similarity score (0-1)." - }, - "career_stage": { - "type": "string", - "description": "undiscovered, developing, mid-level, mainstream, superstar, or legendary." - }, - "recent_momentum": { - "type": "string", - "description": "decline, gradual decline, steady, growth, or explosive growth." - }, - "sp_followers": { - "type": "integer", - "nullable": true - }, - "sp_monthly_listeners": { - "type": "integer", - "nullable": true - } - }, - "additionalProperties": true - }, - "ResearchSimilarResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "artists": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResearchSimilarArtist" - } - }, - "total": { - "type": "integer" - } - } - }, - "ResearchTrackItem": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "album_names": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true - } - }, - "additionalProperties": true - }, - "ResearchTrackResponse": { - "type": "object", - "description": "Track metadata — title, artist, album, release date, popularity, and platform IDs.", - "properties": { - "status": { - "type": "string" - }, - "name": { - "type": "string" - }, - "id": { - "type": "integer", - "description": "Chartmetric track ID" - }, - "isrc": { - "type": "string" - }, - "album_name": { - "type": "string" - }, - "release_date": { - "type": "string" - }, - "artist_names": { - "type": "string" - } - }, - "additionalProperties": true - }, - "ResearchTracksResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "tracks": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResearchTrackItem" - } - } - } - }, - "ResearchUrlEntry": { - "type": "object", - "properties": { - "domain": { - "type": "string", - "description": "Platform name (e.g., spotify, instagram)." - }, - "url": { - "type": "string", - "format": "uri" - } - } - }, - "ResearchUrlsResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "urls": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResearchUrlEntry" - } - } - } - }, - "ResearchVenue": { - "type": "object", - "properties": { - "venue_name": { - "type": "string", - "description": "Name of the venue." - }, - "venue_capacity": { - "type": "integer", - "nullable": true, - "description": "Venue capacity (seats or standing)." - }, - "city_name": { - "type": "string", - "description": "City where the venue is located." - }, - "country": { - "type": "string", - "description": "Two-letter country code." - }, - "events": { - "type": "array", - "description": "Events the artist performed at this venue.", - "items": { - "type": "object", - "additionalProperties": true - } - } - } - }, - "ResearchVenuesResponse": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "venues": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResearchVenue" - } - } - } - }, - "ResearchWebRequest": { - "type": "object", - "required": [ - "query" - ], - "description": "Request body for web research.", - "properties": { - "query": { - "type": "string", - "description": "The search query — what you want to find on the web." - }, - "max_results": { - "type": "integer", - "minimum": 1, - "maximum": 20, - "default": 10, - "description": "Maximum number of results to return." - }, - "country": { - "type": "string", - "minLength": 2, - "maxLength": 2, - "description": "ISO country code for regional results (e.g., 'US', 'GB')." - } - } - }, - "ResearchWebResponse": { - "type": "object", - "description": "Web search results with titles, URLs, and content snippets.", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "results": { - "type": "array", - "description": "Ranked web search results.", - "items": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "url": { - "type": "string" - }, - "content": { - "type": "string" - } - } - } - }, - "formatted": { - "type": "string", - "description": "Results formatted as markdown for easy reading." - } - } - }, - "MusicComposeRequest": { - "type": "object", - "description": "Parameters for generating a song. Provide either a text prompt or a composition_plan.", - "properties": { - "prompt": { - "type": "string", - "description": "Text prompt describing the desired song — mood, genre, instruments, lyrics, structure." - }, - "composition_plan": { - "type": "object", - "description": "Full composition plan for fine-grained control over sections, styles, and lyrics. Use POST /api/music/plan to generate one." - }, - "duration": { - "type": "number", - "description": "Desired duration in seconds.", - "default": 30 - }, - "output_format": { - "type": "string", - "description": "Audio output format (e.g. mp3_44100_192).", - "default": "mp3_44100_192" - }, - "sign_with_c2pa": { - "type": "boolean", - "description": "Sign the output with C2PA content credentials.", - "default": false - } - } - }, - "MusicComposeDetailedRequest": { - "type": "object", - "description": "Parameters for generating a song with metadata and optional word-level timestamps.", - "properties": { - "prompt": { - "type": "string", - "description": "Text prompt describing the desired song — mood, genre, instruments, lyrics, structure." - }, - "composition_plan": { - "type": "object", - "description": "Full composition plan for fine-grained control over sections, styles, and lyrics. Use POST /api/music/plan to generate one." - }, - "duration": { - "type": "number", - "description": "Desired duration in seconds.", - "default": 30 - }, - "output_format": { - "type": "string", - "description": "Audio output format (e.g. mp3_44100_192).", - "default": "mp3_44100_192" - }, - "sign_with_c2pa": { - "type": "boolean", - "description": "Sign the output with C2PA content credentials.", - "default": false - }, - "with_timestamps": { - "type": "boolean", - "description": "Include word-level timestamps in the metadata response.", - "default": false - } - } - }, - "MusicStreamRequest": { - "type": "object", - "description": "Parameters for generating a song with real-time audio streaming.", - "properties": { - "prompt": { - "type": "string", - "description": "Text prompt describing the desired song — mood, genre, instruments, lyrics, structure." - }, - "composition_plan": { - "type": "object", - "description": "Full composition plan for fine-grained control over sections, styles, and lyrics. Use POST /api/music/plan to generate one." - }, - "duration": { - "type": "number", - "description": "Desired duration in seconds.", - "default": 30 - }, - "output_format": { - "type": "string", - "description": "Audio output format (e.g. mp3_44100_192).", - "default": "mp3_44100_192" - }, - "sign_with_c2pa": { - "type": "boolean", - "description": "Sign the output with C2PA content credentials.", - "default": false - } - } - }, - "MusicCreatePlanRequest": { - "type": "object", - "required": [ - "prompt" - ], - "description": "Parameters for creating a composition plan from a text prompt.", - "properties": { - "prompt": { - "type": "string", - "description": "Text prompt describing the desired song." - } - } - }, - "MusicCreatePlanResponse": { - "type": "object", - "description": "A structured composition plan that can be reviewed, edited, and passed to the compose endpoint.", - "properties": { - "plan": { - "type": "object", - "description": "The composition plan with sections, styles, lyrics, and durations.", - "properties": { - "sections": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Section name (e.g. intro, verse, chorus)" - }, - "duration": { - "type": "number", - "description": "Section duration in seconds" - }, - "style": { - "type": "string", - "description": "Style description for this section" - }, - "lyrics": { - "type": "string", - "description": "Lyrics for this section" - } - } - } - } - } - } - } - }, - "MusicErrorResponse": { - "type": "object", - "required": [ - "error" - ], - "description": "Error response from a music endpoint.", - "properties": { - "error": { - "type": "string", - "description": "Error message describing what went wrong." - } - } - } - }, - "securitySchemes": { - "bearerAuth": { - "type": "http", - "scheme": "bearer" - }, - "apiKeyAuth": { - "type": "apiKey", - "in": "header", - "name": "x-api-key", - "description": "Your Recoup API key. [Learn more](/quickstart#api-keys)." - } - } - } -} diff --git a/api-reference/openapi/accounts.json b/api-reference/openapi/accounts.json new file mode 100644 index 0000000..2bcb001 --- /dev/null +++ b/api-reference/openapi/accounts.json @@ -0,0 +1,2655 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Recoup API - Accounts", + "description": "API documentation for the Recoup platform - an AI agent platform for the music industry", + "license": { + "name": "MIT" + }, + "version": "1.0.0" + }, + "servers": [ + { + "url": "https://recoup-api.vercel.app" + } + ], + "paths": { + "/api/accounts/{id}": { + "get": { + "description": "Retrieve detailed account information by ID. Returns the account with associated profile info, emails, and wallet addresses.", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The unique identifier (UUID) of the account", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Account retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetAccountResponse" + } + } + } + }, + "404": { + "description": "Account not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + } + } + } + }, + "/api/accounts/id": { + "get": { + "description": "Retrieve the ID of the authenticated account associated with the provided credentials. This is useful when you have an API key or access token but do not yet know the corresponding accountId.", + "parameters": [], + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "responses": { + "200": { + "description": "Account ID retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetAccountIdResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + } + } + } + }, + "/api/accounts": { + "post": { + "description": "Create a new account or retrieve an existing account by email or wallet address. If an account with the provided email or wallet already exists, returns that account. Otherwise creates a new account and initializes credits.", + "requestBody": { + "description": "Account credentials to create or lookup", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateAccountRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Account created or retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountDataResponse" + } + } + } + }, + "400": { + "description": "Bad request - failed to create account", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + } + } + }, + "patch": { + "description": "Update an existing account's profile information including name, organization, image, instruction, job title, role type, company name, and knowledges. Requires authentication via x-api-key or Authorization Bearer token. The authenticated account may update itself or a permitted account_id override.", + "requestBody": { + "description": "Account fields to update", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateAccountRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Account updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountDataResponse" + } + } + } + }, + "400": { + "description": "Bad request - account not found or update failed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - account override not permitted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + } + } + } + }, + "/api/accounts/artists": { + "post": { + "description": "Add an artist to an account's list of associated artists. If the artist is already associated with the account, returns success without modification.", + "requestBody": { + "description": "Account and artist identifiers", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AddArtistToAccountRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Artist added to account successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AddArtistSuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request - account not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + } + } + } + }, + "/api/organizations": { + "get": { + "description": "Retrieve all organizations that the authenticated account belongs to. Pass account_id to retrieve organizations for a specific account the API key has access to.", + "parameters": [ + { + "name": "account_id", + "in": "query", + "description": "Filter to a specific account. Only applicable when the authenticated account has access to multiple accounts via organization membership.", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Organizations retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetOrganizationsResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid query parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationsErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden - account_id is not a member of the organization or account tried to filter by an account_id they don't have access to", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "post": { + "description": "Create a new organization. The creator is automatically added as a member of the organization.", + "requestBody": { + "description": "Organization creation parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateOrganizationRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Organization created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateOrganizationResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationsErrorResponse" + } + } + } + } + } + } + }, + "/api/organizations/artists": { + "post": { + "description": "Add an artist to an organization. This allows organization members to access and manage the artist. This endpoint is idempotent - calling it multiple times with the same artistId and organizationId will not create duplicate records.", + "requestBody": { + "description": "Artist-organization association parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AddArtistToOrganizationRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Artist added to organization successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AddArtistToOrganizationResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationsErrorResponse" + } + } + } + } + } + } + }, + "/api/subscriptions": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Retrieve subscription information for an account. For accounts with enterprise plans, returns a simplified response indicating enterprise status. For standard accounts, returns the full Stripe subscription object.", + "parameters": [ + { + "name": "accountId", + "in": "query", + "description": "The unique identifier of the account to query", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Subscription information retrieved successfully", + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/SubscriptionResponse" + }, + { + "$ref": "#/components/schemas/EnterpriseSubscriptionResponse" + } + ] + } + } + } + }, + "400": { + "description": "Bad request - missing or invalid accountId", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionErrorResponse" + } + } + } + }, + "404": { + "description": "Account not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionErrorResponse" + } + } + } + } + } + } + }, + "/api/workspaces": { + "post": { + "description": "Create a new workspace account. Workspaces can optionally be linked to an organization.", + "requestBody": { + "description": "Workspace creation parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateWorkspaceRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Workspace created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateWorkspaceResponse" + } + } + } + }, + "400": { + "description": "Bad request - validation error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing authentication", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden - access denied to organization", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api/pulses": { + "get": { + "description": "Retrieve pulse information for the authenticated account. If the account has access to organizations, pass account_id to filter to a specific account within those organizations.", + "parameters": [ + { + "name": "account_id", + "in": "query", + "description": "Filter to a specific account. Only applicable when the authenticated account has access to multiple accounts via organization membership.", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "active", + "in": "query", + "description": "Filter by active status. Set to 'true' to return only active pulses, 'false' for inactive pulses. If not provided, returns all pulses regardless of active status.", + "required": false, + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ] + } + } + ], + "responses": { + "200": { + "description": "Pulses retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PulsesResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid query parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden - account_id is not a member of the organization or account tried to filter by an account_id they don't have access to", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "patch": { + "description": "Update the pulse settings for an account. Use this to enable or disable the pulse. Returns an array of pulses for consistency with the GET endpoint.", + "requestBody": { + "description": "Pulse fields to update", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdatePulseRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Pulse updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PulsesResponse" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api/notifications": { + "post": { + "description": "Send a notification email to the authenticated account's email address via the Resend API. Emails are sent from `Agent by Recoup `. The recipient is automatically resolved from the API key or Bearer token. Supports plain text (rendered as Markdown) or raw HTML bodies, optional CC recipients, custom headers, and an optional room_id to include a chat link in the email footer.", + "requestBody": { + "description": "Notification email payload", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateNotificationRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Notification sent successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotificationResponse" + } + } + } + }, + "400": { + "description": "Validation error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Authentication required", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "502": { + "description": "Email delivery failed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api/admins": { + "get": { + "description": "Check if the authenticated account is a Recoup admin. An account is considered an admin if it is a member of the Recoup organization. No input parameters required — authentication is performed via the x-api-key or Authorization header.", + "parameters": [], + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "responses": { + "200": { + "description": "Admin status retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CheckAdminResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + } + } + } + }, + "/api/admins/sandboxes": { + "get": { + "description": "Returns a list of all accounts and their sandbox usage statistics. Each item includes the account email, total number of sandboxes created, and the timestamp of the most recently created sandbox. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.", + "parameters": [], + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "responses": { + "200": { + "description": "Account sandbox statistics retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AdminSandboxesResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - authenticated account is not a Recoup admin", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + } + } + } + }, + "/api/admins/sandboxes/orgs": { + "get": { + "description": "Returns commit statistics for each repository in the recoupable GitHub organization. Each item includes the repo name, URL, total commit count, latest 5 commit messages, earliest and latest commit timestamps, and the list of account repo URLs that include this org repo as a submodule. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.", + "parameters": [], + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "responses": { + "200": { + "description": "Org repo statistics retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AdminSandboxOrgsResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - authenticated account is not a Recoup admin", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + } + } + } + }, + "/api/admins/emails": { + "get": { + "description": "Returns Resend emails including HTML content. Provide either account_id (returns all emails for an account) or email_id (returns a single email by Resend ID). Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token. Email response shape matches the [Resend Retrieve Email API](https://resend.com/docs/api-reference/emails/retrieve-email).", + "parameters": [ + { + "name": "account_id", + "in": "query", + "description": "The account ID to fetch all emails for. Required if email_id is not provided.", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "email_id", + "in": "query", + "description": "A Resend email ID to fetch a single email. Required if account_id is not provided.", + "required": false, + "schema": { + "type": "string" + } + } + ], + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "responses": { + "200": { + "description": "Emails retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AdminEmailsResponse" + } + } + } + }, + "400": { + "description": "Bad request - must provide either account_id or email_id", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - authenticated account is not a Recoup admin", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + } + } + } + }, + "/api/admins/coding/slack": { + "get": { + "description": "Returns a list of Slack mentions of the Recoup Coding Agent bot, pulled directly from the Slack API as the source of truth. Each entry includes the tagger's information, the prompt they sent, the timestamp, the channel, and any GitHub pull request URLs opened in response. Also returns aggregate pull request statistics. Supports optional time-period filtering. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.", + "parameters": [ + { + "name": "period", + "in": "query", + "description": "Time period to filter tags. One of: all (no date filter), daily (last 24 hours), weekly (last 7 days), monthly (last 30 days). Defaults to all.", + "required": false, + "schema": { + "type": "string", + "enum": [ + "all", + "daily", + "weekly", + "monthly" + ], + "default": "all" + } + } + ], + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "responses": { + "200": { + "description": "Slack tag analytics retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status", + "total", + "total_pull_requests", + "tags_with_pull_requests", + "tags" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "total": { + "type": "integer", + "description": "Total number of times the Coding Agent was tagged in the requested period", + "example": 134 + }, + "total_pull_requests": { + "type": "integer", + "description": "Total number of pull requests opened by the Coding Agent across all tags in the requested period", + "example": 121 + }, + "tags_with_pull_requests": { + "type": "integer", + "description": "Number of tags that resulted in at least one pull request being opened", + "example": 84 + }, + "tags": { + "type": "array", + "description": "List of Slack tag events", + "items": { + "type": "object", + "required": [ + "user_id", + "user_name", + "prompt", + "timestamp", + "channel_id", + "channel_name" + ], + "properties": { + "user_id": { + "type": "string", + "description": "Slack ID of the person who tagged the agent", + "example": "U012AB3CD" + }, + "user_name": { + "type": "string", + "description": "Display name of the person who tagged the agent", + "example": "Jane Smith" + }, + "user_avatar": { + "type": [ + "string", + "null" + ], + "description": "URL of the Slack avatar", + "example": "https://avatars.slack-edge.com/..." + }, + "prompt": { + "type": "string", + "description": "The text of the message sent to the agent", + "example": "add dark mode support to the settings page" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp of the tag event", + "example": "2024-01-15T10:30:00.000Z" + }, + "channel_id": { + "type": "string", + "description": "Slack channel ID where the tag occurred", + "example": "C012AB3CD" + }, + "channel_name": { + "type": "string", + "description": "Human-readable name of the Slack channel", + "example": "dev-team" + }, + "pull_requests": { + "type": "array", + "description": "GitHub pull request URLs opened by the Coding Agent in response to this prompt, parsed from bot replies in the Slack thread", + "items": { + "type": "string", + "format": "uri", + "example": "https://github.com/recoupable/api/pull/42" + }, + "example": [ + "https://github.com/recoupable/api/pull/42" + ] + } + } + } + } + } + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - authenticated account is not a Recoup admin", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + } + } + } + }, + "/api/admins/content/slack": { + "get": { + "description": "Returns a list of Slack mentions of the Recoup Content Agent bot, pulled directly from the Slack API as the source of truth. Each entry includes the tagger's information, the prompt they sent, the timestamp, the channel, and any video link responses. Also returns aggregate video statistics for measuring tag-to-video conversion. Supports optional time-period filtering. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.", + "parameters": [ + { + "name": "period", + "in": "query", + "description": "Time period to filter tags. One of: all (no date filter), daily (last 24 hours), weekly (last 7 days), monthly (last 30 days). Defaults to all.", + "required": false, + "schema": { + "type": "string", + "enum": [ + "all", + "daily", + "weekly", + "monthly" + ], + "default": "all" + } + } + ], + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "responses": { + "200": { + "description": "Slack tag analytics retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status", + "total", + "total_videos", + "tags_with_videos", + "tags" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "total": { + "type": "integer", + "description": "Total number of times the Content Agent was tagged in the requested period", + "example": 18 + }, + "total_videos": { + "type": "integer", + "description": "Total number of videos generated by the Content Agent across all tags in the requested period", + "example": 12 + }, + "tags_with_videos": { + "type": "integer", + "description": "Number of tags that resulted in at least one video being generated", + "example": 10 + }, + "tags": { + "type": "array", + "description": "List of Slack tag events", + "items": { + "type": "object", + "required": [ + "user_id", + "user_name", + "prompt", + "timestamp", + "channel_id", + "channel_name" + ], + "properties": { + "user_id": { + "type": "string", + "description": "Slack ID of the person who tagged the agent", + "example": "U012AB3CD" + }, + "user_name": { + "type": "string", + "description": "Display name of the person who tagged the agent", + "example": "Jane Smith" + }, + "user_avatar": { + "type": [ + "string", + "null" + ], + "description": "URL of the Slack avatar", + "example": "https://avatars.slack-edge.com/..." + }, + "prompt": { + "type": "string", + "description": "The text of the message sent to the agent", + "example": "create a highlight reel for the new single release" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp of the tag event", + "example": "2024-01-15T10:30:00.000Z" + }, + "channel_id": { + "type": "string", + "description": "Slack channel ID where the tag occurred", + "example": "C012AB3CD" + }, + "channel_name": { + "type": "string", + "description": "Human-readable name of the Slack channel", + "example": "content-team" + }, + "video_links": { + "type": "array", + "description": "Video URLs generated by the Content Agent in response to this prompt, parsed from bot replies in the Slack thread", + "items": { + "type": "string", + "format": "uri", + "example": "https://recoupable.com/v/abc123" + }, + "example": [ + "https://recoupable.com/v/abc123" + ] + } + } + } + } + } + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - authenticated account is not a Recoup admin", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + } + } + } + }, + "/api/admins/coding/pr": { + "get": { + "description": "Returns the status (open, closed, or merged) for each provided GitHub pull request URL. Accepts one or more `pull_requests` query parameters containing GitHub PR URLs. Uses the GitHub REST API to check each pull request's state. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.", + "parameters": [ + { + "name": "pull_requests", + "in": "query", + "description": "One or more GitHub pull request URLs to check. Repeat this parameter for each URL. Example: ?pull_requests=https://github.com/org/repo/pull/1&pull_requests=https://github.com/org/repo/pull/2", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "minItems": 1, + "maxItems": 50 + }, + "style": "form", + "explode": true + } + ], + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "responses": { + "200": { + "description": "PR merged status retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status", + "pull_requests" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "pull_requests": { + "type": "array", + "description": "Status for each provided pull request URL", + "items": { + "type": "object", + "required": [ + "url", + "status" + ], + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "The GitHub pull request URL", + "example": "https://github.com/recoupable/api/pull/42" + }, + "status": { + "type": "string", + "enum": [ + "open", + "closed", + "merged" + ], + "description": "The current status of the pull request", + "example": "merged" + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request - missing or invalid pull_requests parameter", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - authenticated account is not a Recoup admin", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + } + } + } + }, + "/api/admins/privy": { + "get": { + "description": "Returns Privy login statistics for a given time period. Results include counts for new accounts (created_at), active accounts (latest_verified_at), total Privy accounts across all time, and the full, unmodified Privy account objects. See [Privy User object documentation](https://docs.privy.io/api-reference/users/get-all) for the complete type definition. Defaults to period=all (no date filter). Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.", + "parameters": [ + { + "name": "period", + "in": "query", + "description": "Time period to filter logins. One of: all (no date filter), daily (last 24 hours), weekly (last 7 days), monthly (last 30 days). Defaults to all.", + "required": false, + "schema": { + "type": "string", + "enum": [ + "all", + "daily", + "weekly", + "monthly" + ], + "default": "all" + } + } + ], + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "responses": { + "200": { + "description": "Privy login statistics retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status", + "total", + "total_new", + "total_active", + "logins" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "total": { + "type": "integer", + "description": "Total number of accounts in Privy across all time (not filtered by period)", + "example": 42 + }, + "total_new": { + "type": "integer", + "description": "Number of accounts created (created_at) within the requested period", + "example": 15 + }, + "total_active": { + "type": "integer", + "description": "Total number of accounts matching either new or active criteria in the requested period", + "example": 30 + }, + "logins": { + "type": "array", + "description": "Full, unmodified Privy account objects. See [Privy User object docs](https://docs.privy.io/api-reference/users/get-all) for the complete type definition.", + "items": { + "type": "object" + } + } + } + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - authenticated account is not a Recoup admin", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccountErrorResponse" + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer" + }, + "apiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "x-api-key", + "description": "Your Recoup API key. [Learn more](/quickstart#api-keys)." + } + }, + "schemas": { + "Account": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the account" + }, + "name": { + "type": "string", + "description": "Account display name" + }, + "image": { + "type": "string", + "nullable": true, + "description": "Profile image URL" + }, + "instruction": { + "type": "string", + "nullable": true, + "description": "Custom AI instructions for this account" + }, + "knowledges": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/Knowledge" + }, + "description": "Knowledge base files attached to this account" + }, + "email": { + "type": "string", + "nullable": true, + "description": "Primary email address" + }, + "wallet_address": { + "type": "string", + "nullable": true, + "description": "Connected wallet address" + } + } + }, + "AccountData": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the account" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "The account ID (same as id, for consistency)" + }, + "name": { + "type": "string", + "description": "Display name of the account" + }, + "email": { + "type": "string", + "format": "email", + "description": "Email address associated with the account" + }, + "wallet": { + "type": "string", + "description": "Wallet address associated with the account" + }, + "image": { + "type": "string", + "format": "uri", + "description": "URL of the account's profile image" + }, + "instruction": { + "type": "string", + "description": "Custom instruction or bio" + }, + "organization": { + "type": "string", + "description": "Organization name" + }, + "job_title": { + "type": "string", + "description": "Job title" + }, + "role_type": { + "type": "string", + "description": "Role type" + }, + "company_name": { + "type": "string", + "description": "Company name" + }, + "knowledges": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Knowledge" + }, + "description": "Knowledge base files attached to this account" + } + } + }, + "AccountDataResponse": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/AccountData", + "description": "The account data" + } + } + }, + "AccountErrorResponse": { + "type": "object", + "required": [ + "status", + "message" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "message": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "AccountSandboxRow": { + "type": "object", + "required": [ + "account_id", + "total_sandboxes", + "last_created_at" + ], + "properties": { + "account_id": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the account", + "example": "04e3aba9-c130-4fb8-8b92-34e95d43e66b" + }, + "total_sandboxes": { + "type": "integer", + "description": "Total number of sandboxes created for this account", + "example": 5 + }, + "last_created_at": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp of the most recently created sandbox for this account", + "example": "2026-03-10T12:00:00Z" + }, + "account_email": { + "type": "string", + "nullable": true, + "description": "The email address of the account. Null if the account has no email set.", + "example": "alice@example.com" + } + }, + "description": "" + }, + "AddArtistSuccessResponse": { + "type": "object", + "required": [ + "success" + ], + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ], + "description": "Indicates the artist was successfully added" + } + } + }, + "AddArtistToAccountRequest": { + "type": "object", + "required": [ + "email", + "artistId" + ], + "properties": { + "email": { + "type": "string", + "format": "email", + "description": "Email address of the account to add the artist to" + }, + "artistId": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the artist to add" + } + } + }, + "AddArtistToOrganizationRequest": { + "type": "object", + "required": [ + "artistId", + "organizationId" + ], + "properties": { + "artistId": { + "type": "string", + "format": "uuid", + "description": "The account ID of the artist to add", + "example": "artist-account-uuid" + }, + "organizationId": { + "type": "string", + "format": "uuid", + "description": "The account ID of the organization", + "example": "org-account-uuid" + } + } + }, + "AddArtistToOrganizationResponse": { + "type": "object", + "required": [ + "status", + "id" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the created artist-organization link" + } + } + }, + "AdminEmailsResponse": { + "type": "object", + "required": [ + "status", + "emails" + ], + "description": "Response containing Resend emails sent for an account", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ], + "description": "Status of the request" + }, + "emails": { + "type": "array", + "description": "List of emails sent for the account, ordered by created_at descending", + "items": { + "$ref": "#/components/schemas/PulseEmailRow" + } + } + } + }, + "AdminSandboxOrgsResponse": { + "type": "object", + "required": [ + "status", + "repos" + ], + "description": "Response containing commit statistics for all org repositories", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ], + "description": "Status of the request" + }, + "repos": { + "type": "array", + "description": "List of org repos with their commit statistics, ordered by total_commits descending", + "items": { + "$ref": "#/components/schemas/OrgRepoRow" + } + } + } + }, + "AdminSandboxesResponse": { + "type": "object", + "required": [ + "status", + "accounts" + ], + "description": "Response containing per-account sandbox statistics for admin use", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ], + "description": "Status of the request" + }, + "accounts": { + "type": "array", + "description": "List of accounts with their sandbox statistics, ordered by most recently active first", + "items": { + "$ref": "#/components/schemas/AccountSandboxRow" + } + } + } + }, + "CheckAdminResponse": { + "type": "object", + "required": [ + "status", + "isAdmin" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "isAdmin": { + "type": "boolean", + "description": "Whether the authenticated account is a Recoup admin" + } + } + }, + "CreateAccountRequest": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email", + "description": "Email address to associate with the account. If an account with this email exists, it will be returned." + }, + "wallet": { + "type": "string", + "description": "Wallet address to associate with the account. If an account with this wallet exists, it will be returned." + } + }, + "description": "At least one of email or wallet should be provided to identify or create an account." + }, + "CreateNotificationRequest": { + "type": "object", + "required": [ + "subject" + ], + "properties": { + "cc": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "description": "Optional CC email addresses", + "example": [ + "cc@example.com" + ] + }, + "subject": { + "type": "string", + "description": "Email subject line", + "example": "Weekly Pulse Report" + }, + "text": { + "type": "string", + "description": "Plain text or Markdown body. Rendered as HTML via Markdown if no `html` is provided.", + "example": "# Pulse Report\n\nHere's your weekly summary." + }, + "html": { + "type": "string", + "description": "Raw HTML body. Takes precedence over `text` when both are provided.", + "example": "

Pulse Report

Here's your weekly summary.

" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Optional custom email headers" + }, + "room_id": { + "type": "string", + "description": "Room ID to include a chat link in the email footer" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the account to send the notification for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, sends the notification for the API key's own account." + } + } + }, + "CreateOrganizationRequest": { + "type": "object", + "required": [ + "name", + "accountId" + ], + "properties": { + "name": { + "type": "string", + "description": "The name of the organization to create", + "example": "My New Label" + }, + "accountId": { + "type": "string", + "format": "uuid", + "description": "The account ID of the creator", + "example": "123e4567-e89b-12d3-a456-426614174000" + } + } + }, + "CreateOrganizationResponse": { + "type": "object", + "required": [ + "status", + "organization" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "organization": { + "$ref": "#/components/schemas/CreatedOrganization", + "description": "The created organization" + } + } + }, + "CreateWorkspaceRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the workspace (defaults to \"Untitled\")" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the account to create the workspace for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, the workspace is created for the API key's own account." + }, + "organization_id": { + "type": "string", + "format": "uuid", + "description": "Organization to link the workspace to" + } + } + }, + "CreateWorkspaceResponse": { + "type": "object", + "required": [ + "workspace" + ], + "properties": { + "workspace": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": "string" + }, + "account_id": { + "type": "string", + "format": "uuid" + }, + "isWorkspace": { + "type": "boolean" + } + } + } + } + }, + "CreatedOrganization": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the new organization account" + }, + "name": { + "type": "string", + "description": "Name of the organization" + } + } + }, + "EnterpriseSubscriptionResponse": { + "type": "object", + "required": [ + "status", + "isEnterprise" + ], + "description": "Response for accounts with enterprise plans", + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "isEnterprise": { + "type": "boolean", + "enum": [ + true + ], + "description": "Indicates that the account has an enterprise plan" + } + } + }, + "Error": { + "required": [ + "error", + "message" + ], + "type": "object", + "properties": { + "error": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + }, + "GetAccountIdResponse": { + "type": "object", + "required": [ + "status", + "accountId" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "accountId": { + "type": "string", + "format": "uuid", + "description": "The unique identifier (UUID) of the authenticated account" + } + } + }, + "GetAccountResponse": { + "type": "object", + "required": [ + "status", + "account" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "account": { + "$ref": "#/components/schemas/Account", + "description": "The account details" + } + } + }, + "GetOrganizationsResponse": { + "type": "object", + "required": [ + "status", + "organizations" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "organizations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Organization" + }, + "description": "List of organizations the account belongs to" + } + } + }, + "Knowledge": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "URL to the knowledge file" + }, + "name": { + "type": "string", + "description": "Name of the knowledge file" + }, + "type": { + "type": "string", + "description": "MIME type of the file" + } + } + }, + "NotificationResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the notification was sent successfully", + "example": true + }, + "message": { + "type": "string", + "description": "Human-readable result message", + "example": "Email sent successfully from Agent by Recoup to user@example.com." + }, + "id": { + "type": "string", + "description": "Resend email ID", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + } + } + }, + "OrgRepoRow": { + "type": "object", + "required": [ + "repo_name", + "repo_url", + "total_commits", + "latest_commit_messages", + "earliest_committed_at", + "latest_committed_at", + "account_repos" + ], + "description": "Commit statistics for a single GitHub org repository", + "properties": { + "repo_name": { + "type": "string", + "description": "Repository name", + "example": "chat" + }, + "repo_url": { + "type": "string", + "description": "Full GitHub HTML URL of the repository", + "example": "https://github.com/recoupable/chat" + }, + "total_commits": { + "type": "integer", + "description": "Total number of commits in the repository", + "example": 5696 + }, + "latest_commit_messages": { + "type": "array", + "description": "Messages from the 5 most recent commits", + "items": { + "type": "string" + }, + "example": [ + "Merge test into main", + "fix: duration stuck at 0ms for in-progress tasks" + ] + }, + "earliest_committed_at": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp of the earliest (first) commit", + "example": "2024-09-27T17:16:01Z" + }, + "latest_committed_at": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp of the most recent commit", + "example": "2026-03-10T19:57:37Z" + }, + "account_repos": { + "type": "array", + "items": { + "type": "object", + "properties": { + "account_id": { + "type": "string" + }, + "email": { + "type": "string", + "nullable": true + }, + "repo_url": { + "type": "string" + } + }, + "required": [ + "account_id", + "repo_url" + ] + }, + "description": "List of accounts using this org repo as a submodule, with account_id, email, and repo_url" + } + } + }, + "Organization": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the membership record" + }, + "organization_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the organization account" + }, + "organization_name": { + "type": "string", + "description": "Display name of the organization" + }, + "organization_image": { + "type": "string", + "nullable": true, + "description": "Organization logo/image URL" + } + } + }, + "OrganizationsErrorResponse": { + "type": "object", + "required": [ + "status", + "message" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "message": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "Pulse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the pulse" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the associated account" + }, + "active": { + "type": "boolean", + "description": "Whether the pulse is active (defaults to true)" + } + } + }, + "PulseEmailRow": { + "type": "object", + "required": [ + "id", + "from", + "to", + "subject", + "created_at", + "last_event" + ], + "description": "A single email record from Resend (full GetEmailResponseSuccess). See [Resend API docs](https://resend.com/docs/api-reference/emails/retrieve-email) for the source of truth.", + "properties": { + "id": { + "type": "string", + "description": "The Resend email ID" + }, + "from": { + "type": "string", + "description": "Sender email address" + }, + "to": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Recipient email addresses" + }, + "cc": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "description": "CC recipient email addresses" + }, + "bcc": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "description": "BCC recipient email addresses" + }, + "reply_to": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "description": "Reply-to email addresses" + }, + "subject": { + "type": "string", + "description": "Email subject line" + }, + "html": { + "type": "string", + "nullable": true, + "description": "HTML content of the email" + }, + "text": { + "type": "string", + "nullable": true, + "description": "Plain text content of the email" + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the email was created" + }, + "scheduled_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "description": "Scheduled send time, if any" + }, + "last_event": { + "type": "string", + "enum": [ + "bounced", + "canceled", + "clicked", + "complained", + "delivered", + "delivery_delayed", + "failed", + "opened", + "queued", + "scheduled", + "sent" + ], + "description": "Most recent delivery event for this email" + }, + "tags": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "name", + "value" + ] + }, + "nullable": true, + "description": "Custom tags attached to the email" + } + } + }, + "PulsesResponse": { + "type": "object", + "required": [ + "status", + "pulses" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ], + "description": "Status of the request" + }, + "pulses": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pulse" + }, + "description": "Array of pulse objects. Contains pulses for the authenticated account. If the account has access to organizations, all organization accounts are included." + }, + "error": { + "type": "string", + "description": "Error message (only present if status is error)" + } + } + }, + "StripeSubscription": { + "type": "object", + "description": "A Stripe subscription object. For detailed information about all available properties, see the Stripe Subscription API documentation: https://docs.stripe.com/api/subscriptions/retrieve", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the subscription" + }, + "object": { + "type": "string", + "enum": [ + "subscription" + ], + "description": "String representing the object's type" + }, + "customer": { + "type": "string", + "description": "ID of the customer who owns this subscription" + }, + "status": { + "type": "string", + "enum": [ + "active", + "canceled", + "incomplete", + "incomplete_expired", + "past_due", + "trialing", + "unpaid" + ], + "description": "The status of the subscription" + }, + "currency": { + "type": "string", + "description": "Three-letter ISO currency code" + }, + "current_period_start": { + "type": "integer", + "description": "Start of the current period (Unix timestamp)" + }, + "current_period_end": { + "type": "integer", + "description": "End of the current period (Unix timestamp)" + }, + "cancel_at_period_end": { + "type": "boolean", + "description": "If true, the subscription will be canceled at the end of the current period" + }, + "created": { + "type": "integer", + "description": "Time at which the subscription was created (Unix timestamp)" + }, + "items": { + "type": "object", + "description": "List of subscription items, each with an attached price", + "properties": { + "object": { + "type": "string", + "enum": [ + "list" + ] + }, + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "object": { + "type": "string", + "enum": [ + "subscription_item" + ] + }, + "price": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit_amount": { + "type": "integer", + "description": "Price amount in cents" + }, + "recurring": { + "type": "object", + "properties": { + "interval": { + "type": "string", + "enum": [ + "day", + "week", + "month", + "year" + ] + }, + "interval_count": { + "type": "integer" + } + } + } + } + }, + "quantity": { + "type": "integer" + } + } + } + }, + "has_more": { + "type": "boolean" + }, + "total_count": { + "type": "integer" + } + } + }, + "latest_invoice": { + "type": "string", + "description": "ID of the most recent invoice for this subscription" + }, + "livemode": { + "type": "boolean", + "description": "Indicates if in live mode (true) or test mode (false)" + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs attached to the subscription" + } + } + }, + "SubscriptionErrorResponse": { + "type": "object", + "required": [ + "status", + "error" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "SubscriptionResponse": { + "type": "object", + "required": [ + "status", + "subscription" + ], + "description": "Response for standard accounts with Stripe subscriptions", + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "subscription": { + "$ref": "#/components/schemas/StripeSubscription", + "description": "The full Stripe subscription object" + } + } + }, + "UpdateAccountRequest": { + "type": "object", + "required": [ + "accountId" + ], + "properties": { + "accountId": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the account to update" + }, + "name": { + "type": "string", + "description": "Display name for the account" + }, + "instruction": { + "type": "string", + "description": "Custom instruction or bio for the account" + }, + "organization": { + "type": "string", + "description": "Organization name associated with the account" + }, + "image": { + "type": "string", + "format": "uri", + "description": "URL of the account's profile image" + }, + "jobTitle": { + "type": "string", + "description": "Job title of the account holder" + }, + "roleType": { + "type": "string", + "description": "Role type within the organization" + }, + "companyName": { + "type": "string", + "description": "Company name associated with the account" + }, + "knowledges": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Knowledge" + }, + "description": "Knowledge base files attached to this account" + } + } + }, + "UpdatePulseRequest": { + "type": "object", + "required": [ + "active" + ], + "properties": { + "active": { + "type": "boolean", + "description": "Whether to enable or disable the pulse", + "example": true + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the account to update the pulse for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, updates the pulse for the API key's own account." + } + } + } + } + } +} diff --git a/api-reference/openapi/content.json b/api-reference/openapi/content.json new file mode 100644 index 0000000..56e3be3 --- /dev/null +++ b/api-reference/openapi/content.json @@ -0,0 +1,4039 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Recoup API - Content", + "description": "API documentation for the Recoup platform - an AI agent platform for the music industry", + "license": { + "name": "MIT" + }, + "version": "1.0.0" + }, + "servers": [ + { + "url": "https://recoup-api.vercel.app" + } + ], + "paths": { + "/api/sandboxes": { + "get": { + "description": "List all sandboxes associated with the authenticated account and their current statuses. Returns sandbox details including lifecycle state, timeout remaining, and creation timestamp. Pass account_id to retrieve sandboxes for a specific account the API key has access to. Authentication is handled via the x-api-key header or Authorization Bearer token.", + "parameters": [ + { + "name": "sandbox_id", + "in": "query", + "required": false, + "description": "Filter by a specific sandbox ID. When provided, returns only the sandbox matching this ID. Must be a sandbox that your account or organization is an admin of.", + "schema": { + "type": "string", + "example": "sbx_abc123def456" + } + }, + { + "name": "account_id", + "in": "query", + "description": "Filter to a specific account. Only applicable when the authenticated account has access to multiple accounts via organization membership.", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Sandboxes retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxesResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - account_id is not a member of the organization or account tried to filter by an account_id they don't have access to", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + } + } + }, + "post": { + "description": "Create a new ephemeral sandbox environment. Optionally executes a command or an OpenCode prompt if provided. Sandboxes are isolated Linux microVMs that can be used to evaluate account-generated code, run AI agent output safely, or execute reproducible tasks. The sandbox will automatically stop after the timeout period. If no command or prompt is provided, the sandbox is created without triggering any background task. Use the prompt parameter as a shortcut to run `opencode run \"\"` in the sandbox. Pass account_id to create a sandbox for a specific account the API key has access to. Authentication is handled via the x-api-key header or Authorization Bearer token.", + "requestBody": { + "description": "Optional command execution parameters. If command and prompt are both omitted, sandbox is created without running any command. Use prompt as a shortcut for running OpenCode.", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSandboxRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Sandbox created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxesResponse" + } + } + } + }, + "400": { + "description": "Bad request - failed to create sandbox", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - account_id is not a member of the organization or account tried to use an account_id they don't have access to", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + } + } + }, + "patch": { + "description": "Set a custom snapshot ID for an account. By default, updates the key owner's account. Pass account_id to target a specific account the API key has access to. This allows accounts to use a specific sandbox snapshot when creating new sandboxes, enabling reproducible environments with pre-configured tools, dependencies, and files.", + "requestBody": { + "description": "Snapshot configuration parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSnapshotRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Snapshot ID updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSnapshotResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid snapshot ID", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - account_id is not a member of the organization or account tried to use an account_id they don't have access to", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + } + } + }, + "delete": { + "description": "Delete a sandbox environment for the authenticated account. This permanently deletes the associated GitHub repository and removes the account's snapshot record from the database. By default, deletes the sandbox for the key owner's account. Pass account_id to target a specific account the API key has access to. Authentication is handled via the x-api-key header or Authorization Bearer token.", + "requestBody": { + "description": "Optional account targeting parameters", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteSandboxRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Sandbox deleted successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteSandboxResponse" + } + } + } + }, + "400": { + "description": "Bad request - failed to delete sandbox", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - account_id is not a member of the organization or account tried to use an account_id they don't have access to", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + } + } + } + }, + "/api/sandboxes/setup": { + "post": { + "description": "Triggers the setup-sandbox background task to create a personal sandbox, provision a GitHub repo, take a snapshot, and shut down. By default, sets up the sandbox for the key owner's account. Pass account_id to target a specific account the API key has access to. Authentication is handled via the x-api-key header or Authorization Bearer token.", + "requestBody": { + "description": "Optional account targeting parameters", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetupSandboxRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Setup task triggered successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetupSandboxResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid account_id format", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + } + } + } + }, + "/api/sandboxes/file": { + "get": { + "description": "Retrieve the raw contents of a file from the authenticated account's sandbox GitHub repository. Resolves the github_repo from the [account's snapshot](/api-reference/sandboxes/list), then fetches the file at the specified path from the repository's main branch. Authentication is handled via the x-api-key header or Authorization Bearer token.", + "parameters": [ + { + "name": "path", + "in": "query", + "required": true, + "description": "The file path within the repository (e.g. \"src/index.ts\" or \"README.md\").", + "schema": { + "type": "string", + "example": "src/index.ts" + } + } + ], + "responses": { + "200": { + "description": "File contents retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxFileResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing or invalid path parameter", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - account does not have access", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + }, + "404": { + "description": "Not found - no snapshot, no github_repo, or file not found in repository", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + } + } + } + }, + "/api/sandboxes/files": { + "post": { + "description": "Upload one or more files to the authenticated account's sandbox GitHub repository. Accepts an array of file URLs and commits each file to the specified directory path within the repository. Supports submodule resolution — if the target path falls within a git submodule, the file is committed to the submodule's repository. Authentication is handled via the x-api-key header or Authorization Bearer token.", + "requestBody": { + "description": "JSON body containing file URLs and target path", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UploadSandboxFilesRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Files uploaded successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UploadSandboxFilesResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing files or invalid path", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - account does not have access", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + }, + "404": { + "description": "Not found - no snapshot or no github_repo configured", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxErrorResponse" + } + } + } + } + } + } + }, + "/api/image/generate": { + "get": { + "servers": [ + { + "url": "https://recoup-api.vercel.app" + } + ], + "description": "Generate high-quality images using AI models. Images are automatically stored on Arweave and include In Process moment metadata for provenance and ownership tracking.", + "parameters": [ + { + "name": "prompt", + "in": "query", + "description": "Text description of the image you want to generate", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "account_id", + "in": "query", + "description": "The unique identifier of the account generating the image", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Image generated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ImageGenerationResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters or invalid input", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ImageGenerationErrorResponse" + } + } + } + } + } + } + }, + "/api/transcribe": { + "post": { + "description": "Transcribe audio files using OpenAI Whisper. The API saves both the original audio file and the generated markdown transcript to the customer's files in Supabase Storage.", + "requestBody": { + "description": "Audio transcription request", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TranscribeAudioRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Audio transcribed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TranscribeAudioResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required fields or invalid audio URL", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TranscribeAudioErrorResponse" + } + } + } + }, + "413": { + "description": "Audio file exceeds the 25MB limit", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TranscribeAudioErrorResponse" + } + } + } + }, + "429": { + "description": "Rate limit exceeded", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TranscribeAudioErrorResponse" + } + } + } + }, + "500": { + "description": "Server error - OpenAI API key not configured", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TranscribeAudioErrorResponse" + } + } + } + } + } + } + }, + "/api/content": { + "patch": { + "description": "Apply edits to content — trim, crop, resize, overlay text, or add an audio track. Accepts video, image, or audio input. Pass a `template` for a preset edit pipeline, or build your own with an `operations` array.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Edit parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateEditRequest" + } + } + } + }, + "responses": { + "202": { + "description": "Edit task triggered successfully. Poll via [GET /api/tasks/runs](/api-reference/tasks/runs) using the returned `runId`.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateEditResponse" + } + } + } + }, + "400": { + "description": "Validation failed — invalid or missing request body fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + } + } + } + }, + "/api/content/create": { + "post": { + "description": "Trigger the content creation pipeline for an artist. Provide `artist_account_id` to identify the target artist. Validates the artist has all required files (face guide, songs) unless overridden via `songs` URLs or `images`, then triggers a background task that generates a short-form video. Returns `runIds` — an array of run IDs that can each be polled via [GET /api/tasks/runs](/api-reference/tasks/runs).", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Content creation parameters including the target artist and optional template/workflow settings", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateRequest" + } + } + } + }, + "responses": { + "202": { + "description": "Pipeline triggered successfully. Returns `runIds` — an array of run IDs. Poll each via [GET /api/tasks/runs](/api-reference/tasks/runs) to check progress.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateResponse" + } + } + } + }, + "400": { + "description": "Validation failed — missing artist identifier, artist is missing required files, or template not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "404": { + "description": "Artist not found — the provided artist_account_id does not match any artist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + } + } + } + }, + "/api/content/templates": { + "get": { + "description": "List all available content creation templates. Templates are optional — every content primitive works without one. When you do use a template, it provides a complete creative recipe: image prompts, video motion config, caption style rules, and edit operations. Returns template ID and description only — enough to pick the right one.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "responses": { + "200": { + "description": "Templates retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentTemplatesResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + } + } + } + }, + "/api/content/templates/{id}": { + "get": { + "description": "Get the full configuration for a specific content creation template. Returns the complete creative recipe including image prompts, video motion config, caption style rules, and edit operations.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Template identifier", + "required": true, + "schema": { + "type": "string", + "example": "artist-caption-bedroom" + } + } + ], + "responses": { + "200": { + "description": "Template detail retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentTemplateDetail" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "404": { + "description": "Template not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "error" + }, + "error": { + "type": "string", + "example": "Template not found" + } + } + } + } + } + } + } + } + }, + "/api/content/validate": { + "get": { + "description": "Check whether an artist has all the required files to run the content creation pipeline. Returns a structured report of each required and recommended file with its status. Required files must be present or the pipeline will fail. Recommended files improve output quality but are not strictly necessary. Provide `artist_account_id` as a query parameter.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "parameters": [ + { + "name": "artist_account_id", + "in": "query", + "description": "UUID of the artist account to validate. Use [GET /api/artists](/api-reference/artists/list) to find artist account IDs.", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "example": "1873859c-dd37-4e9a-9bac-80d3558527a9" + } + } + ], + "responses": { + "200": { + "description": "Validation completed. Check the `ready` field to determine if the artist can run the pipeline.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentValidateResponse" + } + } + } + }, + "400": { + "description": "Bad request — artist_account_id is required", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "404": { + "description": "Artist not found — the provided artist_account_id does not match any artist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + } + } + } + }, + "/api/content/estimate": { + "get": { + "description": "Estimate the cost of running the content creation pipeline. Calculates per-step and per-video costs based on current pricing. Supports comparing multiple workflow profiles (e.g., premium vs. budget) and projecting batch costs. This endpoint is informational only — it does not trigger any pipeline execution or spend credits.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "parameters": [ + { + "name": "lipsync", + "in": "query", + "description": "Which workflow to estimate. `false` for image-to-video, `true` for audio-to-video. If omitted, estimates the default image-to-video workflow.", + "required": false, + "schema": { + "type": "boolean", + "example": false + } + }, + { + "name": "batch", + "in": "query", + "description": "Number of videos to project costs for. Use this to answer questions like \"how much would 30 videos cost?\"", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "default": 1, + "example": 1 + } + }, + { + "name": "compare", + "in": "query", + "description": "When `true`, returns estimates for all available workflow profiles (premium, budget, mid) for side-by-side comparison.", + "required": false, + "schema": { + "type": "boolean", + "default": false, + "example": false + } + } + ], + "responses": { + "200": { + "description": "Cost estimate calculated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentEstimateResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + } + } + } + }, + "/api/content-agent/{platform}": { + "post": { + "description": "Webhook endpoint for the Recoup Content Agent Slack bot. Receives @mention events from Slack and triggers content generation for the mentioned artist. The bot parses the mention text for ` [template] [batch=N] [lipsync]`, validates the artist, calls POST /api/content/create, and starts a background polling task that reports results back to the Slack thread.\n\nFor Slack, also handles `url_verification` challenges during app setup.", + "parameters": [ + { + "name": "platform", + "in": "path", + "description": "Chat platform identifier. Currently supports `slack`.", + "required": true, + "schema": { + "type": "string", + "enum": [ + "slack" + ] + } + } + ], + "requestBody": { + "description": "Slack Events API payload (app_mention event or url_verification challenge)", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "Slack Events API envelope — the shape depends on the event type" + } + } + } + }, + "responses": { + "200": { + "description": "Event processed successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ok": { + "type": "boolean" + } + } + } + } + } + }, + "404": { + "description": "Unknown platform" + } + } + } + }, + "/api/content-agent/callback": { + "post": { + "description": "Internal callback endpoint for the `poll-content-run` Trigger.dev task. Receives content generation results and posts them back to the originating Slack thread. Authenticated via the `x-callback-secret` header.\n\nThis endpoint is not intended for external use — it is called automatically by the polling task when content runs complete, fail, or time out.", + "requestBody": { + "description": "Content generation results from the polling task", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "threadId", + "status" + ], + "properties": { + "threadId": { + "type": "string", + "description": "Chat SDK thread identifier for the originating Slack thread" + }, + "status": { + "type": "string", + "enum": [ + "completed", + "failed", + "timeout" + ], + "description": "Overall status of the content generation batch" + }, + "results": { + "type": "array", + "description": "Per-run results", + "items": { + "type": "object", + "required": [ + "runId", + "status" + ], + "properties": { + "runId": { + "type": "string", + "description": "Trigger.dev run ID" + }, + "status": { + "type": "string", + "enum": [ + "completed", + "failed", + "timeout" + ] + }, + "videoUrl": { + "type": "string", + "description": "URL of the generated video (when completed)" + }, + "captionText": { + "type": "string", + "description": "Generated caption text (when completed)" + }, + "error": { + "type": "string", + "description": "Error message (when failed)" + } + } + } + }, + "message": { + "type": "string", + "description": "Optional human-readable message" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Callback processed and results posted to Slack", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "ok" + } + } + } + } + } + }, + "400": { + "description": "Invalid request body" + }, + "401": { + "description": "Missing or invalid callback secret" + } + }, + "security": [ + { + "callbackSecret": [] + } + ] + } + }, + "/api/content/upscale": { + "post": { + "description": "Upscale an image or video to higher resolution. Pass the URL and specify the type. Returns the upscaled URL.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Upscale parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateUpscaleRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Media upscaled successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateUpscaleResponse" + } + } + } + }, + "400": { + "description": "Validation failed — invalid or missing request body fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + } + } + } + }, + "/api/content/analyze": { + "post": { + "description": "Analyze a video and answer questions about it. Pass a video URL and a text prompt — for example, \"Describe what happens\" or \"Rate the visual quality 1-10.\" Returns the generated text.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Video analysis parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateAnalyzeRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Video analyzed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateAnalyzeResponse" + } + } + } + }, + "400": { + "description": "Validation failed — invalid or missing request body fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "502": { + "description": "Video analysis failed upstream", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + } + } + } + }, + "/api/content/caption": { + "post": { + "description": "Generate a short caption from a topic. Returns the text content and default styling (font, color, size).", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Text generation parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateTextRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Text generated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateTextResponse" + } + } + } + }, + "400": { + "description": "Validation failed — invalid or missing request body fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + } + } + } + }, + "/api/content/image": { + "post": { + "description": "Generate an image from a text prompt. Pass a `reference_image_url` to guide the output toward a specific look or subject. Returns the image URL.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Image generation parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateImageRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Image generated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateImageResponse" + } + } + } + }, + "400": { + "description": "Validation failed — invalid or missing request body fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + } + } + } + }, + "/api/content/video": { + "post": { + "description": "Generate a video. Set `mode` to control what kind of video you get:\n\n- `prompt` — create a video from a text description\n- `animate` — animate a still image\n- `reference` — use an image as a style/subject reference (not the first frame)\n- `extend` — continue an existing video\n- `first-last` — generate a video that transitions between two images\n- `lipsync` — sync face movement to an audio clip\n\nIf `mode` is omitted, it's inferred from the inputs you provide.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Video generation parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateVideoRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Video generated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateVideoResponse" + } + } + } + }, + "400": { + "description": "Validation failed — invalid or missing request body fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + } + } + } + }, + "/api/content/transcribe": { + "post": { + "description": "Transcribe audio into text with word-level timestamps. Pass one or more audio file URLs in `audio_urls`. Returns the full transcript and an array of timed segments.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Audio transcription parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateAudioRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Song transcribed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentCreateAudioResponse" + } + } + } + }, + "400": { + "description": "Validation failed — invalid or missing request body fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentErrorResponse" + } + } + } + } + } + } + }, + "/api/music/compose": { + "post": { + "description": "Generate a song from a text prompt or a composition plan. The prompt can describe mood, genre, instruments, lyrics, and structure. Alternatively, pass a full composition_plan for fine-grained control over sections, styles, and lyrics. Returns binary audio in the requested format (default MP3).", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Music composition parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicComposeRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Audio generated successfully", + "headers": { + "song-id": { + "schema": { + "type": "string" + }, + "description": "Unique identifier for the generated song" + } + }, + "content": { + "audio/mpeg": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "400": { + "description": "Validation failed — invalid or missing request body fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + } + } + } + }, + "/api/music/compose/detailed": { + "post": { + "description": "Generate a song with metadata and optional word-level timestamps. Returns a multipart/mixed response: the first part is JSON metadata (song ID, duration, seed, etc.) and the second part is binary audio. Use with_timestamps to get precise timing for each word in the lyrics.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Music composition parameters with optional timestamps", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicComposeDetailedRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Audio and metadata generated successfully. Response is multipart/mixed: JSON metadata followed by binary audio.", + "content": { + "multipart/mixed": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "400": { + "description": "Validation failed — invalid or missing request body fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + } + } + } + }, + "/api/music/stream": { + "post": { + "description": "Generate a song and stream audio chunks in real time. Use this endpoint when you want to begin playback before the full song is generated. The response streams binary audio chunks as they are produced.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Music streaming parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicStreamRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Audio stream started successfully", + "headers": { + "song-id": { + "schema": { + "type": "string" + }, + "description": "Unique identifier for the generated song" + } + }, + "content": { + "audio/mpeg": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "400": { + "description": "Validation failed — invalid or missing request body fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + } + } + } + }, + "/api/music/plan": { + "post": { + "description": "Create a composition plan from a text prompt. A composition plan is a structured representation of a song — sections, styles, lyrics, and durations — that you can review and tweak before passing to the compose endpoint. This endpoint is free and does not consume credits.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Plan creation parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicCreatePlanRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Composition plan created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicCreatePlanResponse" + } + } + } + }, + "400": { + "description": "Validation failed — invalid or missing request body fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + } + } + } + }, + "/api/music/video-to-music": { + "post": { + "description": "Generate background music from video files. Upload 1–10 video files via multipart/form-data (max 200 MB total). The AI analyzes the video content and generates music that matches the mood, pacing, and style. Optionally provide a text description and style tags to guide the output.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Video files and optional generation parameters", + "required": true, + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "files": { + "type": "array", + "items": { + "type": "string", + "format": "binary" + }, + "minItems": 1, + "maxItems": 10, + "description": "Video files to analyze (max 200 MB total)" + }, + "description": { + "type": "string", + "maxLength": 1000, + "description": "Optional text description to guide the music generation" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "maxItems": 10, + "description": "Optional style tags to influence the output (max 10)" + }, + "sign_with_c2pa": { + "type": "boolean", + "default": false, + "description": "Sign the output with C2PA content credentials" + }, + "output_format": { + "type": "string", + "description": "Audio output format (e.g. mp3_44100_192)" + } + }, + "required": [ + "files" + ] + } + } + } + }, + "responses": { + "200": { + "description": "Background music generated successfully", + "headers": { + "song-id": { + "schema": { + "type": "string" + }, + "description": "Unique identifier for the generated song" + } + }, + "content": { + "audio/mpeg": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "400": { + "description": "Validation failed — invalid or missing request body fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + } + } + } + }, + "/api/music/stem-separation": { + "post": { + "description": "Separate an audio file into individual stems (vocals, drums, bass, etc.). Upload an audio file via multipart/form-data. Choose between two-stem separation (vocals + instrumental) or six-stem separation (vocals, drums, bass, guitar, piano, other). Returns a ZIP archive containing the separated stems.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Audio file and separation parameters", + "required": true, + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "file": { + "type": "string", + "format": "binary", + "description": "Audio file to separate into stems" + }, + "stem_variation_id": { + "type": "string", + "enum": [ + "two_stems_v1", + "six_stems_v1" + ], + "default": "six_stems_v1", + "description": "Stem separation mode. `two_stems_v1` produces vocals + instrumental. `six_stems_v1` produces vocals, drums, bass, guitar, piano, and other." + }, + "sign_with_c2pa": { + "type": "boolean", + "default": false, + "description": "Sign the output with C2PA content credentials" + }, + "output_format": { + "type": "string", + "description": "Audio output format (e.g. mp3_44100_192)" + } + }, + "required": [ + "file" + ] + } + } + } + }, + "responses": { + "200": { + "description": "Stems separated successfully. Returns a ZIP archive containing the individual stems.", + "content": { + "application/zip": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "400": { + "description": "Validation failed — invalid or missing request body fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MusicErrorResponse" + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer" + }, + "apiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "x-api-key", + "description": "Your Recoup API key. [Learn more](/quickstart#api-keys)." + } + }, + "schemas": { + "ArweaveTransaction": { + "type": "object", + "description": "Arweave transaction object for the stored image", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the Arweave transaction" + }, + "last_tx": { + "type": "string", + "description": "Last transaction reference" + }, + "owner": { + "type": "string", + "description": "Owner address of the transaction" + }, + "tags": { + "type": "array", + "items": { + "type": "object" + }, + "description": "Tags associated with the transaction" + }, + "target": { + "type": "string", + "description": "Target address (empty for data transactions)" + }, + "quantity": { + "type": "string", + "description": "Amount transferred (typically '0' for data transactions)" + }, + "data": { + "type": "string", + "description": "Transaction data (may be empty in response)" + }, + "reward": { + "type": "string", + "description": "Mining reward for the transaction" + }, + "signature": { + "type": "string", + "description": "Transaction signature" + }, + "format": { + "type": "integer", + "description": "Transaction format version" + } + } + }, + "ContentCreateAnalyzeRequest": { + "type": "object", + "required": [ + "video_url", + "prompt" + ], + "properties": { + "video_url": { + "type": "string", + "format": "uri", + "description": "Publicly accessible URL of the video to analyze. Supported formats: MP4, MOV, AVI, and other FFmpeg-compatible formats. Maximum duration: 1 hour." + }, + "prompt": { + "type": "string", + "maxLength": 2000, + "description": "A text prompt that guides the analysis. Can be instructive, descriptive, or phrased as a question. Examples: \"Describe the key moments in this video\", \"Generate 5 SEO keywords for this video\"." + }, + "temperature": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.2, + "description": "Controls the randomness of the text output. Lower values produce more focused results. Defaults to `0.2`." + }, + "max_tokens": { + "type": "integer", + "minimum": 1, + "maximum": 4096, + "description": "Maximum number of tokens to generate. If omitted, uses the model default." + } + } + }, + "ContentCreateAnalyzeResponse": { + "type": "object", + "required": [ + "text" + ], + "properties": { + "text": { + "type": "string", + "description": "The generated analysis text based on the video and prompt." + }, + "finish_reason": { + "type": "string", + "enum": [ + "stop", + "length" + ], + "nullable": true, + "description": "`stop` if the generation completed normally. `length` if truncated at the token limit." + }, + "usage": { + "type": "object", + "nullable": true, + "properties": { + "output_tokens": { + "type": "integer", + "description": "Number of tokens in the generated text." + } + } + } + } + }, + "ContentCreateAudioRequest": { + "type": "object", + "required": [ + "audio_urls" + ], + "properties": { + "audio_urls": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "minItems": 1, + "description": "Audio file URLs to transcribe" + }, + "model": { + "type": "string", + "description": "fal.ai model ID. Defaults to fal-ai/whisper" + } + } + }, + "ContentCreateAudioResponse": { + "type": "object", + "required": [ + "songUrl", + "fullLyrics", + "segments", + "segmentCount" + ], + "properties": { + "songUrl": { + "type": "string", + "description": "URL of the transcribed song" + }, + "fullLyrics": { + "type": "string", + "description": "Complete transcribed lyrics as a single string" + }, + "segments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentCreateAudioSegment" + }, + "description": "Timestamped lyric segments" + }, + "segmentCount": { + "type": "number", + "description": "Total number of segments returned" + } + } + }, + "ContentCreateAudioSegment": { + "type": "object", + "required": [ + "start", + "end", + "text" + ], + "properties": { + "start": { + "type": "number", + "description": "Segment start time in seconds" + }, + "end": { + "type": "number", + "description": "Segment end time in seconds" + }, + "text": { + "type": "string", + "description": "Transcribed text for this segment" + } + } + }, + "ContentCreateEditRequest": { + "type": "object", + "description": "Must provide at least one input (video_url, image_url, or audio_url)", + "properties": { + "video_url": { + "type": "string", + "format": "uri", + "description": "Input video URL" + }, + "image_url": { + "type": "string", + "format": "uri", + "description": "Input image URL" + }, + "audio_url": { + "type": "string", + "format": "uri", + "description": "Input audio URL" + }, + "template": { + "type": "string", + "description": "Template name for deterministic edit config. If provided, operations are read from the template. See [GET /api/content/templates](/api-reference/content/templates) for available options." + }, + "operations": { + "type": "array", + "description": "Array of edit operations to apply in order. Required if template is not provided.", + "items": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "trim", + "crop", + "resize", + "overlay_text", + "mux_audio" + ], + "description": "Operation type" + }, + "start": { + "type": "number", + "description": "Start time in seconds (trim)" + }, + "duration": { + "type": "number", + "description": "Duration in seconds (trim)" + }, + "aspect": { + "type": "string", + "description": "Aspect ratio e.g. 9:16 (crop)" + }, + "width": { + "type": "integer", + "description": "Width in pixels (crop/resize)" + }, + "height": { + "type": "integer", + "description": "Height in pixels (crop/resize)" + }, + "content": { + "type": "string", + "description": "Text content (overlay_text)" + }, + "font": { + "type": "string", + "description": "Font name (overlay_text)" + }, + "color": { + "type": "string", + "description": "Text color (overlay_text)" + }, + "stroke_color": { + "type": "string", + "description": "Text stroke color (overlay_text)" + }, + "max_font_size": { + "type": "number", + "description": "Maximum font size (overlay_text)" + }, + "position": { + "type": "string", + "enum": [ + "top", + "center", + "bottom" + ], + "description": "Text position (overlay_text)" + }, + "audio_url": { + "type": "string", + "format": "uri", + "description": "Audio URL to mux (mux_audio)" + }, + "replace": { + "type": "boolean", + "description": "Replace existing audio (mux_audio)" + } + } + } + }, + "output_format": { + "type": "string", + "enum": [ + "mp4", + "webm", + "mov" + ], + "default": "mp4", + "description": "Output format" + } + } + }, + "ContentCreateEditResponse": { + "type": "object", + "required": [ + "runId", + "status" + ], + "properties": { + "runId": { + "type": "string", + "description": "Background task run ID. Poll via [GET /api/tasks/runs](/api-reference/tasks/runs) to check progress." + }, + "status": { + "type": "string", + "enum": [ + "triggered" + ], + "description": "Status of the edit task" + } + } + }, + "ContentCreateErrorResponse": { + "type": "object", + "required": [ + "error" + ], + "description": "Returned when the artist is missing required files or the template is not found. Includes actionable instructions for resolving each issue.", + "properties": { + "error": { + "type": "string", + "description": "Human-readable error summary", + "example": "Artist 'new-artist' is not ready for content creation" + }, + "ready": { + "type": "boolean", + "description": "Always `false` when this error is returned", + "example": false + }, + "missing": { + "type": "array", + "description": "List of missing files with severity and fix instructions. Only present when the artist fails validation.", + "items": { + "$ref": "#/components/schemas/ContentMissingFile" + } + }, + "available_templates": { + "type": "array", + "description": "List of valid template names. Only present when the requested template was not found.", + "items": { + "type": "string" + }, + "example": [ + "artist-caption-bedroom", + "artist-caption-outside", + "artist-caption-stage" + ] + } + } + }, + "ContentCreateImageRequest": { + "type": "object", + "properties": { + "template": { + "type": "string", + "description": "Optional template ID. When provided, uses the template's image prompt, reference images, and style rules. Caller params override template defaults. Artist context overrides template style when available. See [GET /api/content/templates](/api-reference/content/templates) for available options." + }, + "prompt": { + "type": "string", + "description": "Optional prompt to guide image generation" + }, + "reference_image_url": { + "type": "string", + "format": "uri", + "description": "URL of a reference image for conditioning the generation" + }, + "images": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "description": "Optional reference image URLs to guide generation" + }, + "model": { + "type": "string", + "description": "fal.ai model ID. Defaults to fal-ai/nano-banana-pro/edit" + } + } + }, + "ContentCreateImageResponse": { + "type": "object", + "required": [ + "imageUrl" + ], + "properties": { + "imageUrl": { + "type": "string", + "format": "uri", + "description": "URL of the generated image" + } + } + }, + "ContentCreateRequest": { + "type": "object", + "description": "Parameters for triggering the content creation pipeline.", + "properties": { + "artist_account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the artist account to create content for. Use [GET /api/artists](/api-reference/artists/list) to find artist account IDs.", + "example": "1873859c-dd37-4e9a-9bac-80d3558527a9" + }, + "template": { + "type": "string", + "description": "Optional template ID for content generation. Defines the visual style, scene, and prompt configuration. When omitted, the pipeline runs in malleable mode using only the params you provide. See GET /api/content/templates for available options.", + "example": "artist-caption-stage" + }, + "lipsync": { + "type": "boolean", + "description": "Whether to generate video with lip-synced audio. When `true`, uses an audio-to-video model that bakes audio into the video for lip movement. When `false`, generates video from the image alone and overlays audio in post. If omitted, the template's default workflow is used.", + "example": false + }, + "caption_length": { + "type": "string", + "enum": [ + "short", + "medium", + "long" + ], + "description": "Controls the length of the generated caption text. `short` produces 1-2 lines (punchy, minimal). `medium` produces 1-2 sentences. `long` produces a paragraph (stream of consciousness style). Defaults to `short`.", + "default": "short", + "example": "short" + }, + "upscale": { + "type": "boolean", + "description": "Whether to upscale the generated image and video for higher resolution and detail. Adds approximately 2 minutes to the pipeline. Defaults to `false`.", + "default": false, + "example": false + }, + "batch": { + "type": "integer", + "minimum": 1, + "maximum": 30, + "description": "Number of videos to generate in parallel. Each video independently selects a random reference image, song clip, and mood variation. The response always returns `runIds` as an array. Defaults to `1`.", + "default": 1, + "example": 1 + }, + "songs": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional list of song slugs or public URLs to use for the audio track. Song slugs match filenames without extension from the artist's `songs/` directory (e.g. `\"hiccups\"` for `hiccups.mp3`). Public URLs (e.g. `\"https://example.com/my-song.mp3\"`) are downloaded, transcribed, and clipped directly — bypassing the Git repo. When omitted, all songs in the artist's repo are eligible.", + "example": [ + "hiccups", + "https://example.com/unreleased-track.mp3" + ] + }, + "images": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "description": "Optional list of public image URLs to use as face guides instead of the artist's default `face-guide.png` from their GitHub repo. The first image is used as the primary face guide. Useful when the caller wants to override the default face reference.", + "example": [ + "https://example.com/face.png" + ] + } + }, + "required": [ + "artist_account_id" + ] + }, + "ContentCreateResponse": { + "type": "object", + "required": [ + "runIds", + "status", + "artist_account_id" + ], + "description": "Confirmation that the content creation pipeline has been triggered. Always returns `runIds` as an array — even for a single run, it contains one element.", + "properties": { + "runIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of run IDs. Poll each via [GET /api/tasks/runs](/api-reference/tasks/runs). For single runs this contains one element.", + "example": [ + "run_abc123def456" + ] + }, + "status": { + "type": "string", + "enum": [ + "triggered" + ], + "description": "Indicates the pipeline has been triggered" + }, + "artist_account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the artist account the pipeline is running for", + "example": "1873859c-dd37-4e9a-9bac-80d3558527a9" + }, + "template": { + "type": [ + "string", + "null" + ], + "description": "Template ID when a preset pipeline is used; null in malleable mode.", + "example": null + }, + "lipsync": { + "type": "boolean", + "description": "Whether lip-sync mode is enabled", + "example": false + }, + "failed": { + "type": "integer", + "description": "Number of triggers that failed. Only present when some triggers failed.", + "example": 0 + } + } + }, + "ContentCreateTextRequest": { + "type": "object", + "required": [ + "topic" + ], + "properties": { + "template": { + "type": "string", + "description": "Optional template ID. When provided, injects the template's caption guide (tone, rules, formats) and examples into the LLM prompt. Caller's topic is still required. See [GET /api/content/templates](/api-reference/content/templates) for available options." + }, + "topic": { + "type": "string", + "description": "The subject or theme for caption generation" + }, + "length": { + "type": "string", + "enum": [ + "short", + "medium", + "long" + ], + "default": "short", + "description": "Desired text length" + } + } + }, + "ContentCreateTextResponse": { + "type": "object", + "required": [ + "content", + "color", + "borderColor", + "maxFontSize" + ], + "properties": { + "content": { + "type": "string", + "description": "Generated on-screen text content" + }, + "font": { + "type": [ + "string", + "null" + ], + "description": "Font name for the text, or null for default" + }, + "color": { + "type": "string", + "description": "Text color as a CSS color value", + "example": "#FFFFFF" + }, + "borderColor": { + "type": "string", + "description": "Text border/stroke color as a CSS color value", + "example": "#000000" + }, + "maxFontSize": { + "type": "number", + "description": "Maximum font size in pixels", + "example": 48 + } + } + }, + "ContentCreateUpscaleRequest": { + "type": "object", + "required": [ + "url", + "type" + ], + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL of the image or video to upscale" + }, + "type": { + "type": "string", + "enum": [ + "image", + "video" + ], + "description": "Whether the input is an image or video" + } + } + }, + "ContentCreateUpscaleResponse": { + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL of the upscaled image or video" + } + } + }, + "ContentCreateVideoRequest": { + "type": "object", + "properties": { + "template": { + "type": "string", + "description": "Optional template ID. When provided, the template's video config (moods, movements) is used as the motion prompt. Caller params override template defaults. See [GET /api/content/templates](/api-reference/content/templates) for available options." + }, + "mode": { + "type": "string", + "enum": [ + "prompt", + "animate", + "reference", + "extend", + "first-last", + "lipsync" + ], + "description": "What kind of video to generate. If omitted, inferred from the inputs you provide." + }, + "prompt": { + "type": "string", + "description": "Text describing the video content, motion, or how to continue/extend" + }, + "image_url": { + "type": "string", + "format": "uri", + "description": "Image URL. Used as the first frame (animate), style reference (reference), start frame (first-last), or face source (lipsync)" + }, + "end_image_url": { + "type": "string", + "format": "uri", + "description": "End frame image URL. Only used with `first-last` mode" + }, + "video_url": { + "type": "string", + "format": "uri", + "description": "Video URL to extend. Only used with `extend` mode (max 8 seconds input)" + }, + "audio_url": { + "type": "string", + "format": "uri", + "description": "Audio URL for lipsync mode. The generated face will move in sync with this audio" + }, + "aspect_ratio": { + "type": "string", + "enum": [ + "auto", + "16:9", + "9:16" + ], + "default": "auto", + "description": "Aspect ratio of the output video" + }, + "duration": { + "type": "string", + "enum": [ + "4s", + "6s", + "7s", + "8s" + ], + "default": "8s", + "description": "Duration of the generated video" + }, + "resolution": { + "type": "string", + "enum": [ + "720p", + "1080p", + "4k" + ], + "default": "720p", + "description": "Output resolution" + }, + "negative_prompt": { + "type": "string", + "description": "Describe what you do NOT want in the video" + }, + "generate_audio": { + "type": "boolean", + "default": false, + "description": "Generate audio for the video" + }, + "model": { + "type": "string", + "description": "Override the model. Auto-selected based on mode if omitted" + } + } + }, + "ContentCreateVideoResponse": { + "type": "object", + "required": [ + "videoUrl" + ], + "properties": { + "videoUrl": { + "type": "string", + "format": "uri", + "description": "URL of the generated video" + } + } + }, + "ContentErrorResponse": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string", + "description": "Error message describing what went wrong", + "example": "Unauthorized" + } + } + }, + "ContentEstimateComparison": { + "type": "object", + "required": [ + "cheapest", + "cheapestPerVideo", + "mostExpensive", + "mostExpensivePerVideo", + "savingsPercent" + ], + "description": "Summary comparing the cheapest and most expensive workflow options.", + "properties": { + "cheapest": { + "type": "string", + "description": "Name of the cheapest workflow profile", + "example": "Budget (no upscale, LTX video)" + }, + "cheapestPerVideo": { + "type": "number", + "format": "float", + "description": "Cost per video for the cheapest workflow", + "example": 0.18 + }, + "mostExpensive": { + "type": "string", + "description": "Name of the most expensive workflow profile", + "example": "Current (audio-to-video)" + }, + "mostExpensivePerVideo": { + "type": "number", + "format": "float", + "description": "Cost per video for the most expensive workflow", + "example": 0.95 + }, + "savingsPercent": { + "type": "integer", + "description": "Percentage savings between the cheapest and most expensive workflows", + "example": 81 + } + } + }, + "ContentEstimateResponse": { + "type": "object", + "required": [ + "workflows" + ], + "description": "Cost estimates based on current pricing. When `compare` is `false`, the `workflows` array contains a single entry. When `true`, it contains all available profiles.", + "properties": { + "workflows": { + "type": "array", + "description": "One or more workflow cost breakdowns", + "items": { + "$ref": "#/components/schemas/ContentWorkflowEstimate" + } + }, + "comparison": { + "description": "Side-by-side summary. Only present when `compare` is `true` and multiple workflows are returned.", + "$ref": "#/components/schemas/ContentEstimateComparison" + }, + "batch": { + "type": "object", + "description": "Batch cost projection. Only present when `batch` > 1.", + "properties": { + "count": { + "type": "integer", + "description": "Number of videos in the batch", + "example": 30 + }, + "cheapestTotal": { + "type": "number", + "format": "float", + "description": "Total cost for the batch using the cheapest workflow", + "example": 5.4 + }, + "mostExpensiveTotal": { + "type": "number", + "format": "float", + "description": "Total cost for the batch using the most expensive workflow", + "example": 28.5 + } + } + } + } + }, + "ContentMissingFile": { + "type": "object", + "required": [ + "file", + "severity", + "description", + "fix" + ], + "description": "A missing file that prevents or degrades content creation.", + "properties": { + "file": { + "type": "string", + "description": "Relative path of the missing file within the artist directory", + "example": "context/images/face-guide.png" + }, + "severity": { + "type": "string", + "enum": [ + "required", + "recommended" + ], + "description": "`required` means the pipeline will fail without this file. `recommended` means the pipeline will run but output quality is degraded.", + "example": "required" + }, + "description": { + "type": "string", + "description": "What this file is used for in the pipeline", + "example": "Face guide image used for AI image generation" + }, + "fix": { + "type": "string", + "description": "Actionable instructions for creating or adding the missing file", + "example": "Generate a face guide using fal-ai/nano-banana-pro/edit with 2-3 reference photos of the artist" + } + } + }, + "ContentStepEstimate": { + "type": "object", + "required": [ + "name", + "model", + "cost", + "note" + ], + "description": "Cost details for a single pipeline step.", + "properties": { + "name": { + "type": "string", + "description": "Pipeline step name", + "example": "Generate Image" + }, + "model": { + "type": "string", + "description": "The AI model or service used for this step", + "example": "fal-ai/nano-banana-pro/edit" + }, + "cost": { + "type": "number", + "format": "float", + "description": "Estimated cost for this step in USD", + "example": 0.04 + }, + "unit": { + "type": "string", + "description": "Billing unit type (e.g., `images`, `seconds`, `megapixels`). Not present for free steps.", + "example": "images" + }, + "unitPrice": { + "type": "number", + "format": "float", + "description": "Price per billing unit in USD. Not present for free steps.", + "example": 0.04 + }, + "note": { + "type": "string", + "description": "Human-readable calculation detail", + "example": "1 call" + } + } + }, + "ContentTemplate": { + "type": "object", + "required": [ + "id", + "description" + ], + "description": "A content creation template — a complete creative recipe defining visual style, composition, caption rules, and edit operations. Templates are optional; all primitives work without one.", + "properties": { + "id": { + "type": "string", + "description": "Template identifier. Pass this as the template field in content primitive requests or POST /api/content/create.", + "example": "artist-caption-bedroom" + }, + "description": { + "type": "string", + "description": "Human-readable description of the template's visual style", + "example": "Moody bedroom selfie. Artist on camera with deadpan expression, purple LED lighting, dark room. Short blunt captions in lowercase. Vertical 9:16 video, 8 seconds. Best for: introspective songs, vulnerable moments, daily content. Requires: face image, audio." + } + } + }, + "ContentTemplateDetail": { + "type": "object", + "required": [ + "id", + "description" + ], + "description": "Full configuration for a content creation template including image prompts, video motion config, caption style rules, and edit operations.", + "properties": { + "id": { + "type": "string", + "description": "Template identifier", + "example": "artist-caption-bedroom" + }, + "description": { + "type": "string", + "description": "Human-readable description of the template", + "example": "Moody bedroom selfie. Artist on camera with deadpan expression, purple LED lighting, dark room." + }, + "image": { + "type": "object", + "description": "Image generation configuration", + "properties": { + "prompt": { + "type": "string", + "description": "Default image prompt used when no caller prompt is provided" + }, + "reference_images": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "description": "Reference image URLs for style conditioning" + }, + "style_rules": { + "type": "object", + "description": "Style constraints (lighting, colors, composition)" + } + } + }, + "video": { + "type": "object", + "description": "Video generation configuration", + "properties": { + "moods": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Mood descriptors for motion prompt generation" + }, + "movements": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Camera/subject movement descriptors" + } + } + }, + "caption": { + "type": "object", + "description": "Caption generation configuration", + "properties": { + "guide": { + "type": "object", + "description": "Caption style guide", + "properties": { + "tone": { + "type": "string", + "description": "Voice and tone direction" + }, + "rules": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Style rules for caption generation" + }, + "formats": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Allowed caption formats" + } + } + }, + "examples": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Example captions for few-shot prompting" + } + } + }, + "edit": { + "type": "object", + "description": "Post-processing edit operations", + "properties": { + "operations": { + "type": "array", + "description": "Default edit operations applied during post-processing", + "items": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "trim", + "crop", + "resize", + "overlay_text", + "mux_audio" + ], + "description": "Operation type" + }, + "start": { + "type": "number", + "description": "Start time in seconds (trim)" + }, + "duration": { + "type": "number", + "description": "Duration in seconds (trim)" + }, + "aspect": { + "type": "string", + "description": "Aspect ratio e.g. 9:16 (crop)" + }, + "width": { + "type": "integer", + "description": "Width in pixels (crop/resize)" + }, + "height": { + "type": "integer", + "description": "Height in pixels (crop/resize)" + }, + "content": { + "type": "string", + "description": "Text content (overlay_text)" + }, + "font": { + "type": "string", + "description": "Font name (overlay_text)" + }, + "color": { + "type": "string", + "description": "Text color (overlay_text)" + }, + "stroke_color": { + "type": "string", + "description": "Text stroke color (overlay_text)" + }, + "max_font_size": { + "type": "number", + "description": "Maximum font size (overlay_text)" + }, + "position": { + "type": "string", + "enum": [ + "top", + "center", + "bottom" + ], + "description": "Text position (overlay_text)" + }, + "audio_url": { + "type": "string", + "format": "uri", + "description": "Audio URL to mux (mux_audio)" + }, + "replace": { + "type": "boolean", + "description": "Replace existing audio (mux_audio)" + } + } + } + } + } + } + } + }, + "ContentTemplatesResponse": { + "type": "object", + "required": [ + "templates" + ], + "description": "List of available content creation templates.", + "properties": { + "templates": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentTemplate" + } + } + } + }, + "ContentValidateResponse": { + "type": "object", + "required": [ + "ready", + "artist_account_id" + ], + "description": "Validation report for an artist's content creation readiness.", + "properties": { + "ready": { + "type": "boolean", + "description": "`true` if the artist has all required files and the pipeline can run. `false` if required files are missing.", + "example": true + }, + "artist_account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the artist account that was validated", + "example": "1873859c-dd37-4e9a-9bac-80d3558527a9" + }, + "songs": { + "type": "integer", + "description": "Number of songs found in the artist's `songs/` directory", + "example": 17 + }, + "templates": { + "type": "array", + "description": "Available templates that can be used with this artist", + "items": { + "type": "string" + }, + "example": [ + "artist-caption-bedroom", + "artist-caption-outside", + "artist-caption-stage" + ] + }, + "checks": { + "type": "object", + "description": "Per-file validation results. Only present when `ready` is `true`.", + "properties": { + "face_guide": { + "$ref": "#/components/schemas/ContentValidationCheck" + }, + "artist_context": { + "$ref": "#/components/schemas/ContentValidationCheck" + }, + "audience_context": { + "$ref": "#/components/schemas/ContentValidationCheck" + }, + "songs": { + "allOf": [ + { + "$ref": "#/components/schemas/ContentValidationCheck" + }, + { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "Number of songs found", + "example": 17 + } + } + } + ] + } + } + }, + "missing": { + "type": "array", + "description": "List of missing files with severity and fix instructions. Only present when `ready` is `false`.", + "items": { + "$ref": "#/components/schemas/ContentMissingFile" + } + } + } + }, + "ContentValidationCheck": { + "type": "object", + "required": [ + "status" + ], + "description": "Status of a single validation check.", + "properties": { + "status": { + "type": "string", + "enum": [ + "ok", + "missing", + "warning" + ], + "description": "Whether the file was found", + "example": "ok" + } + } + }, + "ContentWorkflowEstimate": { + "type": "object", + "required": [ + "name", + "perVideo", + "steps" + ], + "description": "Cost breakdown for a single workflow profile.", + "properties": { + "name": { + "type": "string", + "description": "Workflow profile name", + "example": "Current (image-to-video)" + }, + "perVideo": { + "type": "number", + "format": "float", + "description": "Total estimated cost per video in USD", + "example": 0.82 + }, + "steps": { + "type": "array", + "description": "Per-step cost breakdown showing where the money goes", + "items": { + "$ref": "#/components/schemas/ContentStepEstimate" + } + }, + "costBreakdown": { + "type": "object", + "description": "Summary of the biggest cost driver", + "properties": { + "mostExpensiveStep": { + "type": "string", + "description": "Name of the step that costs the most", + "example": "Generate Video" + }, + "mostExpensivePercent": { + "type": "integer", + "description": "Percentage of total cost from the most expensive step", + "example": 68 + } + } + } + } + }, + "CreateSandboxRequest": { + "type": "object", + "description": "Request body for creating a new sandbox. All fields are optional - if no command or prompt is provided, sandbox is created without triggering a command execution task. Use prompt as a shortcut to run OpenCode with a given prompt instead of specifying command/args manually.", + "properties": { + "command": { + "type": "string", + "minLength": 1, + "description": "The command to execute in the sandbox environment. If omitted, the sandbox is created without running any command.", + "example": "ls" + }, + "args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional arguments to pass to the command.", + "example": [ + "-la", + "/home" + ] + }, + "cwd": { + "type": "string", + "description": "Optional working directory for command execution.", + "example": "/home/user" + }, + "prompt": { + "type": "string", + "minLength": 1, + "description": "A prompt to pass to OpenCode in the sandbox. When provided, the sandbox will execute `opencode run \"\"`. Cannot be used together with command.", + "example": "create a hello world index.html" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the account to create the sandbox for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, creates the sandbox for the API key's own account." + } + } + }, + "DeleteSandboxRequest": { + "type": "object", + "properties": { + "account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the account to delete the sandbox for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, deletes the sandbox for the API key's own account." + } + } + }, + "DeleteSandboxResponse": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ], + "description": "Status of the delete operation" + }, + "deleted_snapshot": { + "nullable": true, + "description": "The snapshot record that was deleted. Null if no snapshot existed for the account.", + "$ref": "#/components/schemas/UpdateSnapshotResponse" + }, + "error": { + "type": "string", + "description": "Error message (only present if status is error)" + } + } + }, + "FileTreeEntry": { + "type": "object", + "required": [ + "path", + "type", + "sha" + ], + "description": "A single entry in a GitHub repository file tree", + "properties": { + "path": { + "type": "string", + "description": "The file or directory path relative to the repository root", + "example": "src/index.ts" + }, + "type": { + "type": "string", + "enum": [ + "blob", + "tree" + ], + "description": "The type of entry: blob for files, tree for directories" + }, + "sha": { + "type": "string", + "description": "The SHA hash of the entry", + "example": "abc123def456" + }, + "size": { + "type": "integer", + "description": "The size of the file in bytes. Only present for blob entries.", + "example": 1024 + } + } + }, + "GeneratedImage": { + "type": "object", + "description": "A generated image file from the AI model", + "properties": { + "base64": { + "type": "string", + "description": "Image file as a base64 encoded string" + }, + "uint8Array": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Image file as a Uint8Array (represented as array of numbers in JSON)" + }, + "mediaType": { + "type": "string", + "description": "The IANA media type of the file (e.g., 'image/png', 'image/jpeg')" + } + } + }, + "ImageGenerationErrorResponse": { + "type": "object", + "properties": { + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "ImageGenerationResponse": { + "type": "object", + "description": "Response from the image generation endpoint, extending Experimental_GenerateImageResult from the AI SDK", + "properties": { + "images": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeneratedImage" + }, + "description": "Array of generated image objects" + }, + "warnings": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of warning messages, if any" + }, + "responses": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ImageResponseMeta" + }, + "description": "Array of response metadata from the AI provider" + }, + "providerMetadata": { + "$ref": "#/components/schemas/ImageProviderMetadata" + }, + "usage": { + "$ref": "#/components/schemas/ImageUsage" + }, + "imageUrl": { + "type": "string", + "description": "Permanent Arweave URL where the image is stored" + }, + "arweaveResult": { + "$ref": "#/components/schemas/ArweaveTransaction" + }, + "moment": { + "$ref": "#/components/schemas/InProcessMoment" + } + } + }, + "ImageProviderMetadata": { + "type": "object", + "description": "Metadata from the AI provider about the generation", + "properties": { + "model": { + "type": "string", + "description": "The AI model used for generation (e.g., 'dall-e-3', 'gpt-image-1')" + }, + "size": { + "type": "string", + "description": "The size of the generated image (e.g., '1024x1024')" + } + } + }, + "ImageResponseMeta": { + "type": "object", + "description": "Response metadata from the AI provider", + "properties": { + "finishReason": { + "type": "string", + "description": "Reason the generation finished (e.g., 'stop')" + } + } + }, + "ImageUsage": { + "type": "object", + "description": "Token usage information for the image generation", + "properties": { + "promptTokens": { + "type": "integer", + "description": "Number of tokens used in the prompt" + }, + "completionTokens": { + "type": "integer", + "description": "Number of tokens used in the completion (typically 0 for image generation)" + }, + "totalTokens": { + "type": "integer", + "description": "Total tokens used" + } + } + }, + "InProcessMoment": { + "type": "object", + "description": "In Process moment metadata for provenance and ownership tracking", + "properties": { + "contractAddress": { + "type": "string", + "description": "Smart contract address for the moment" + }, + "tokenId": { + "type": "string", + "description": "Token ID of the minted moment" + }, + "hash": { + "type": "string", + "description": "Transaction hash of the moment mint" + }, + "chainId": { + "type": "integer", + "description": "Chain ID (e.g., 8453 for Base)" + } + } + }, + "MusicComposeDetailedRequest": { + "type": "object", + "description": "Parameters for generating a song with metadata and optional word-level timestamps.", + "properties": { + "prompt": { + "type": "string", + "description": "Text prompt describing the desired song — mood, genre, instruments, lyrics, structure." + }, + "composition_plan": { + "type": "object", + "description": "Full composition plan for fine-grained control over sections, styles, and lyrics. Use POST /api/music/plan to generate one." + }, + "duration": { + "type": "number", + "description": "Desired duration in seconds.", + "default": 30 + }, + "output_format": { + "type": "string", + "description": "Audio output format (e.g. mp3_44100_192).", + "default": "mp3_44100_192" + }, + "sign_with_c2pa": { + "type": "boolean", + "description": "Sign the output with C2PA content credentials.", + "default": false + }, + "with_timestamps": { + "type": "boolean", + "description": "Include word-level timestamps in the metadata response.", + "default": false + } + } + }, + "MusicComposeRequest": { + "type": "object", + "description": "Parameters for generating a song. Provide either a text prompt or a composition_plan.", + "properties": { + "prompt": { + "type": "string", + "description": "Text prompt describing the desired song — mood, genre, instruments, lyrics, structure." + }, + "composition_plan": { + "type": "object", + "description": "Full composition plan for fine-grained control over sections, styles, and lyrics. Use POST /api/music/plan to generate one." + }, + "duration": { + "type": "number", + "description": "Desired duration in seconds.", + "default": 30 + }, + "output_format": { + "type": "string", + "description": "Audio output format (e.g. mp3_44100_192).", + "default": "mp3_44100_192" + }, + "sign_with_c2pa": { + "type": "boolean", + "description": "Sign the output with C2PA content credentials.", + "default": false + } + } + }, + "MusicCreatePlanRequest": { + "type": "object", + "required": [ + "prompt" + ], + "description": "Parameters for creating a composition plan from a text prompt.", + "properties": { + "prompt": { + "type": "string", + "description": "Text prompt describing the desired song." + } + } + }, + "MusicCreatePlanResponse": { + "type": "object", + "description": "A structured composition plan that can be reviewed, edited, and passed to the compose endpoint.", + "properties": { + "plan": { + "type": "object", + "description": "The composition plan with sections, styles, lyrics, and durations.", + "properties": { + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Section name (e.g. intro, verse, chorus)" + }, + "duration": { + "type": "number", + "description": "Section duration in seconds" + }, + "style": { + "type": "string", + "description": "Style description for this section" + }, + "lyrics": { + "type": "string", + "description": "Lyrics for this section" + } + } + } + } + } + } + } + }, + "MusicErrorResponse": { + "type": "object", + "required": [ + "error" + ], + "description": "Error response from a music endpoint.", + "properties": { + "error": { + "type": "string", + "description": "Error message describing what went wrong." + } + } + }, + "MusicStreamRequest": { + "type": "object", + "description": "Parameters for generating a song with real-time audio streaming.", + "properties": { + "prompt": { + "type": "string", + "description": "Text prompt describing the desired song — mood, genre, instruments, lyrics, structure." + }, + "composition_plan": { + "type": "object", + "description": "Full composition plan for fine-grained control over sections, styles, and lyrics. Use POST /api/music/plan to generate one." + }, + "duration": { + "type": "number", + "description": "Desired duration in seconds.", + "default": 30 + }, + "output_format": { + "type": "string", + "description": "Audio output format (e.g. mp3_44100_192).", + "default": "mp3_44100_192" + }, + "sign_with_c2pa": { + "type": "boolean", + "description": "Sign the output with C2PA content credentials.", + "default": false + } + } + }, + "Sandbox": { + "type": "object", + "required": [ + "sandboxId", + "sandboxStatus", + "timeout", + "createdAt" + ], + "description": "A sandbox environment instance", + "properties": { + "sandboxId": { + "type": "string", + "description": "Unique identifier for the sandbox", + "example": "sbx_abc123def456" + }, + "sandboxStatus": { + "type": "string", + "enum": [ + "pending", + "running", + "stopping", + "stopped", + "failed" + ], + "description": "Current lifecycle state of the sandbox", + "example": "running" + }, + "timeout": { + "type": "integer", + "description": "Milliseconds remaining before the sandbox stops automatically", + "example": 300000 + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp when the sandbox was created", + "example": "2024-01-15T10:30:00.000Z" + }, + "runId": { + "type": "string", + "description": "Unique identifier for the command execution run. Only present if a command was provided when creating the sandbox. Use this with [GET /api/tasks/runs](/api-reference/tasks/runs) to check the status and retrieve results.", + "example": "run_xyz789abc123" + } + } + }, + "SandboxErrorResponse": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string", + "description": "Error message describing what went wrong", + "example": "Failed to create sandbox" + } + } + }, + "SandboxFileResponse": { + "type": "object", + "required": [ + "status", + "content" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the operation" + }, + "content": { + "type": "string", + "description": "The raw text content of the file" + } + } + }, + "SandboxesResponse": { + "type": "object", + "required": [ + "status", + "sandboxes" + ], + "description": "Response containing sandbox information", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ], + "description": "Status of the request" + }, + "sandboxes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Sandbox" + }, + "description": "Array of sandbox objects" + }, + "snapshot_id": { + "type": "string", + "description": "The account's saved snapshot ID used for creating new sandboxes. Null if no snapshot has been saved.", + "example": "snap_abc123def456", + "nullable": true + }, + "github_repo": { + "type": "string", + "description": "The GitHub repository URL associated with the account's sandbox environment. Used as the filesystem source when restoring sandboxes.", + "example": "https://github.com/username/repo", + "nullable": true + }, + "filetree": { + "type": "array", + "nullable": true, + "description": "The recursive file tree of the account's GitHub repository. Null if no github_repo is set or if the fetch fails.", + "items": { + "$ref": "#/components/schemas/FileTreeEntry" + } + }, + "error": { + "type": "string", + "description": "Error message (only present if status is error)" + } + } + }, + "SetupSandboxRequest": { + "type": "object", + "properties": { + "account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the account to set up the sandbox for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, sets up the sandbox for the API key's own account." + } + } + }, + "SetupSandboxResponse": { + "type": "object", + "required": [ + "status", + "runId" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the setup operation" + }, + "runId": { + "type": "string", + "description": "The Trigger.dev run ID for the setup-sandbox background task. Use this with [GET /api/tasks/runs](/api-reference/tasks/runs) to check the status and retrieve results.", + "example": "run_abc123def456" + } + } + }, + "TranscribeAudioErrorResponse": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "TranscribeAudioRequest": { + "type": "object", + "required": [ + "audio_url", + "account_id", + "artist_account_id" + ], + "properties": { + "audio_url": { + "type": "string", + "description": "Public URL to the audio file (mp3, wav, m4a, webm)", + "example": "https://example.com/song.mp3" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "Owner account ID for file storage", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "artist_account_id": { + "type": "string", + "format": "uuid", + "description": "Artist account ID for file storage", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "title": { + "type": "string", + "description": "Optional title for the audio and transcription files", + "example": "My Song" + }, + "include_timestamps": { + "type": "boolean", + "description": "Whether to include timestamps in the markdown transcript", + "default": false + } + } + }, + "TranscribeAudioResponse": { + "type": "object", + "required": [ + "success", + "audioFile", + "transcriptFile", + "text" + ], + "properties": { + "success": { + "type": "boolean", + "description": "Whether the transcription was successful" + }, + "audioFile": { + "$ref": "#/components/schemas/TranscribeFileInfo", + "description": "Information about the saved audio file" + }, + "transcriptFile": { + "$ref": "#/components/schemas/TranscribeFileInfo", + "description": "Information about the saved transcript file" + }, + "text": { + "type": "string", + "description": "The full transcription text" + }, + "language": { + "type": "string", + "description": "Detected language code (e.g., 'en', 'es', 'fr')" + } + } + }, + "TranscribeFileInfo": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the file record in the database" + }, + "fileName": { + "type": "string", + "description": "Name of the saved file" + }, + "storageKey": { + "type": "string", + "description": "Storage path in Supabase Storage" + } + } + }, + "UpdateSnapshotRequest": { + "type": "object", + "required": [], + "properties": { + "snapshotId": { + "type": "string", + "description": "The snapshot ID to set for the account. This snapshot will be used as the base environment when creating new sandboxes.", + "example": "snap_abc123def456" + }, + "github_repo": { + "type": "string", + "format": "uri", + "description": "The GitHub repository URL to associate with the account's sandbox environment. Must be a valid URL.", + "example": "https://github.com/org/repo" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the account to update the snapshot for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, updates the snapshot for the API key's own account." + } + } + }, + "UpdateSnapshotResponse": { + "type": "object", + "required": [ + "account_id", + "snapshot_id", + "expires_at", + "github_repo", + "created_at" + ], + "properties": { + "account_id": { + "type": "string", + "format": "uuid", + "description": "The account ID this snapshot belongs to", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "snapshot_id": { + "type": "string", + "description": "The snapshot ID that was set for the account", + "example": "snap_abc123def456" + }, + "expires_at": { + "type": "string", + "format": "date-time", + "description": "When the snapshot expires", + "example": "2027-01-01T00:00:00.000Z" + }, + "github_repo": { + "type": "string", + "nullable": true, + "description": "The GitHub repository URL associated with the sandbox", + "example": "https://github.com/org/repo" + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "description": "When the snapshot record was created", + "example": "2025-01-01T00:00:00.000Z" + } + } + }, + "UploadSandboxFilesRequest": { + "type": "object", + "required": [ + "files" + ], + "properties": { + "path": { + "type": "string", + "description": "The target directory path within the repository to upload files to. Defaults to the repository root if omitted.", + "example": "assets/images" + }, + "files": { + "type": "array", + "items": { + "type": "object", + "required": [ + "url", + "name" + ], + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "The URL of the file to upload", + "example": "https://example.com/files/album-cover.png" + }, + "name": { + "type": "string", + "description": "The filename to use when committing to the repository", + "example": "album-cover.png" + } + } + }, + "description": "Array of files to upload, each with a URL and target filename" + }, + "message": { + "type": "string", + "description": "Optional commit message. Defaults to 'Upload files via API'.", + "example": "Add new album artwork" + } + } + }, + "UploadSandboxFilesResponse": { + "type": "object", + "required": [ + "status", + "uploaded" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the operation" + }, + "uploaded": { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "The full path of the uploaded file in the repository" + }, + "sha": { + "type": "string", + "description": "The git SHA of the created/updated file" + } + } + }, + "description": "Array of uploaded file details" + } + } + } + } + } +} diff --git a/api-reference/openapi/releases.json b/api-reference/openapi/releases.json new file mode 100644 index 0000000..a2a3f87 --- /dev/null +++ b/api-reference/openapi/releases.json @@ -0,0 +1,3191 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Recoup API - Releases", + "description": "API documentation for the Recoup platform - an AI agent platform for the music industry", + "license": { + "name": "MIT" + }, + "version": "1.0.0" + }, + "servers": [ + { + "url": "https://recoup-api.vercel.app" + } + ], + "paths": { + "/api/tasks": { + "get": { + "description": "Retrieve scheduled tasks. The response includes recent_runs (last 5 runs) and upcoming (next scheduled run times) sourced directly from the Trigger.dev API. Supports filtering by id, account_id, or artist_account_id.", + "parameters": [ + { + "name": "id", + "in": "query", + "description": "Filter by task ID (UUID). Returns a single task matching the provided ID.", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "account_id", + "in": "query", + "description": "Filter tasks to only include those for the specified account.", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "artist_account_id", + "in": "query", + "description": "Filter tasks to only include those for the specified artist account.", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Tasks retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TasksResponse" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "post": { + "description": "Create a new scheduled task. All fields are required. The response shape matches the GET endpoint (an array containing the created task).", + "requestBody": { + "description": "Task to create", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateTaskRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Task created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TasksResponse" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "patch": { + "description": "Update an existing scheduled task. Only the id field is required; any additional fields you include will be updated on the task. The response shape matches the GET endpoint (an array containing the updated task).", + "requestBody": { + "description": "Task fields to update", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateTaskRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Task updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TasksResponse" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "delete": { + "description": "Delete an existing scheduled task by its ID. Returns the status of the delete operation.", + "requestBody": { + "description": "Task to delete", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteTaskRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Task deleted successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteTaskResponse" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api/tasks/runs": { + "get": { + "description": "Returns an array of task runs. When runId is provided, the array contains that single run. When omitted, returns recent runs for the authenticated account. Use account_id to query runs for a specific account within your organizations.", + "parameters": [ + { + "name": "runId", + "in": "query", + "description": "The unique identifier of a specific task run to retrieve. If omitted, returns a list of recent runs for the authenticated account.", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of runs to return when listing (ignored when runId is provided). Default 20, max 100.", + "required": false, + "schema": { + "type": "integer", + "default": 20, + "minimum": 1, + "maximum": 100 + } + }, + { + "name": "account_id", + "in": "query", + "description": "Filter runs by account ID. When provided, returns runs tagged with account:. Only applicable when the authenticated account has access to multiple accounts via organization membership.", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Task runs retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TaskRunListResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden - account_id is not accessible with the provided credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Task run not found (only when runId is provided)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api/artists": { + "get": { + "description": "Retrieve artists accessible to the authenticated account. The account is derived from the API key or Bearer token. When org_id is omitted, returns only the account's own artists. Pass org_id to view artists in a specific organization. Pass account_id to filter to a specific account the API key has access to.", + "parameters": [ + { + "name": "account_id", + "in": "query", + "description": "Filter to a specific account's artists. Only applicable when the authenticated account has access to multiple accounts via organization membership.", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "org_id", + "in": "query", + "description": "Filter to artists in a specific organization. When omitted, returns only personal (non-organization) artists.", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Artists retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistsResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistsErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid authentication" + }, + "403": { + "description": "Forbidden - account_id is not accessible with the provided credentials" + } + } + }, + "post": { + "description": "Create a new artist account. The artist can optionally be linked to an organization.", + "requestBody": { + "description": "Artist creation parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateArtistRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Artist created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateArtistResponse" + } + } + } + }, + "400": { + "description": "Bad request - validation error or invalid JSON", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateArtistError" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api/artist/segments": { + "get": { + "description": "Retrieve all segments associated with an artist. This endpoint should be called before using the Segment Fans endpoint to obtain the necessary segment IDs. Supports pagination.", + "parameters": [ + { + "name": "artist_account_id", + "in": "query", + "description": "The unique identifier of the artist account to fetch segments for", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "page", + "in": "query", + "description": "The page number to retrieve (default: 1)", + "required": false, + "schema": { + "type": "integer", + "default": 1 + } + }, + { + "name": "limit", + "in": "query", + "description": "The number of records per page (default: 20, max: 100)", + "required": false, + "schema": { + "type": "integer", + "default": 20, + "maximum": 100 + } + } + ], + "responses": { + "200": { + "description": "Segments retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistSegmentsResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistSegmentsErrorResponse" + } + } + } + } + } + } + }, + "/api/artist/socials": { + "get": { + "description": "Retrieve all social media profiles associated with an artist. This endpoint should be called before using the Social Posts endpoint to obtain the necessary social IDs.", + "parameters": [ + { + "name": "artist_account_id", + "in": "query", + "description": "The unique identifier of the artist account to fetch social profiles for", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Social profiles retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistSocialsResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistSocialsErrorResponse" + } + } + } + } + } + } + }, + "/api/artist/socials/scrape": { + "post": { + "description": "Trigger scrape jobs for all social profiles linked to an artist. Provide an artist_account_id, and the API will look up the artist's socials and invoke a scraping job for each social profile. Each scrape returns Apify run metadata so you can poll for status and retrieve results.", + "requestBody": { + "description": "Artist to scrape socials for", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistSocialsScrapeRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Scrape jobs triggered successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistSocialsScrapeResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistSocialsErrorResponse" + } + } + } + } + } + } + }, + "/api/artist-profile": { + "get": { + "description": "Retrieve comprehensive profile information for an artist across all connected social media platforms, including profile details and post metrics.", + "parameters": [ + { + "name": "artist_account_id", + "in": "query", + "description": "The unique identifier of the artist account to fetch profile data for", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Artist profile retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistProfileResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistProfileErrorResponse" + } + } + } + } + } + } + }, + "/api/segment/fans": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Retrieve all social profiles from fans within a specific segment. This endpoint should be called after obtaining segment IDs from the Artist Segments endpoint. Supports pagination for large fan lists.", + "parameters": [ + { + "name": "segment_id", + "in": "query", + "description": "The unique identifier of the segment to fetch fans for", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "page", + "in": "query", + "description": "The page number to retrieve (default: 1)", + "required": false, + "schema": { + "type": "integer", + "default": 1 + } + }, + { + "name": "limit", + "in": "query", + "description": "The number of records per page (default: 20, max: 100)", + "required": false, + "schema": { + "type": "integer", + "default": 20, + "maximum": 100 + } + } + ], + "responses": { + "200": { + "description": "Segment fans retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SegmentFansResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SegmentFansErrorResponse" + } + } + } + } + } + } + }, + "/api/fans": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Retrieve all social profiles from fans of an artist across all platforms. This endpoint aggregates fan data from all connected social media platforms. Supports pagination for large fan lists.", + "parameters": [ + { + "name": "artist_account_id", + "in": "query", + "description": "The unique identifier of the artist account to fetch fans for", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "page", + "in": "query", + "description": "The page number to retrieve (default: 1)", + "required": false, + "schema": { + "type": "integer", + "default": 1 + } + }, + { + "name": "limit", + "in": "query", + "description": "The number of records per page (default: 20, max: 100)", + "required": false, + "schema": { + "type": "integer", + "default": 20, + "maximum": 100 + } + } + ], + "responses": { + "200": { + "description": "Artist fans retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistFansResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistFansErrorResponse" + } + } + } + } + } + } + }, + "/api/songs": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Retrieve songs from the database with optional filtering by ISRC (International Standard Recording Code) or artist account. This endpoint joins the songs table with song_artists and accounts tables to provide comprehensive song information.", + "parameters": [ + { + "name": "isrc", + "in": "query", + "description": "International Standard Recording Code to filter by specific song", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "artist_account_id", + "in": "query", + "description": "Artist account ID to filter songs by artist", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Songs retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SongsResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SongsErrorResponse" + } + } + } + }, + "404": { + "description": "No songs found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SongsErrorResponse" + } + } + } + } + } + }, + "post": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Bulk create or fetch songs by ISRC. For each song, the API attempts to look up metadata via internal search. If no data is found, optional fallback fields (name, album, notes, artists) are used.", + "requestBody": { + "description": "Array of songs to create or fetch", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSongsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Songs created or fetched successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SongsResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SongsErrorResponse" + } + } + } + } + } + } + }, + "/api/catalogs": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Retrieve catalogs associated with a specific account. The endpoint joins account_catalogs with catalogs to return catalog metadata for the specified account.", + "parameters": [ + { + "name": "account_id", + "in": "query", + "description": "The unique identifier of the account to query", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Catalogs retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogsResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing or invalid account_id", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogsErrorResponse" + } + } + } + }, + "404": { + "description": "Account not found or no catalogs found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogsErrorResponse" + } + } + } + } + } + }, + "post": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Create new catalogs or link existing catalogs to an account. If catalog_id is provided, links the existing catalog. If name is provided without catalog_id, creates a new catalog. If both are provided, catalog_id takes priority.", + "requestBody": { + "description": "Array of catalogs to create or link", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateCatalogsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Catalogs created or linked successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogsResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid parameters or catalog_id not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogsErrorResponse" + } + } + } + } + } + }, + "delete": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Unlink catalogs from an account. If no other accounts are linked to a catalog after removal, the catalog is automatically deleted (cascading to catalog_songs). Otherwise, only the account-catalog relationship is removed.", + "requestBody": { + "description": "Array of catalog-account pairs to remove", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteCatalogsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Catalogs unlinked successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogsResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing catalog_id or account_id", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogsErrorResponse" + } + } + } + } + } + } + }, + "/api/catalogs/songs": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Retrieve songs within a specific catalog with pagination support. This endpoint joins catalog_songs with songs, song_artists, and accounts to provide comprehensive song information for a given catalog.", + "parameters": [ + { + "name": "catalog_id", + "in": "query", + "description": "The unique identifier of the catalog to query songs for", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "artistName", + "in": "query", + "description": "Optional. Filters songs to only include those with matching artist name", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "page", + "in": "query", + "description": "Page number for pagination (default: 1)", + "required": false, + "schema": { + "type": "integer", + "default": 1 + } + }, + { + "name": "limit", + "in": "query", + "description": "Number of songs per page (default: 20, max: 100)", + "required": false, + "schema": { + "type": "integer", + "default": 20, + "maximum": 100 + } + } + ], + "responses": { + "200": { + "description": "Catalog songs retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogSongsResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing or invalid catalog_id", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogSongsErrorResponse" + } + } + } + }, + "404": { + "description": "Catalog not found or no songs in catalog", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogSongsErrorResponse" + } + } + } + } + } + }, + "post": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Batch add songs to a catalog by ISRC. For each song, the API attempts to look up metadata via internal search. If no data is found, optional fallback fields (name, album, notes, artists) are used.", + "requestBody": { + "description": "Array of songs to add to catalog", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AddCatalogSongsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Songs added to catalog successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogSongsResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogSongsErrorResponse" + } + } + } + } + } + }, + "delete": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Batch remove songs from a catalog by ISRC. Deletes the relationship in catalog_songs for each catalog_id and ISRC pair.", + "requestBody": { + "description": "Array of songs to remove from catalog", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteCatalogSongsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Songs removed from catalog successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogSongsResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing catalog_id or isrc", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatalogSongsErrorResponse" + } + } + } + } + } + } + }, + "/api/songs/analyze/presets": { + "get": { + "description": "Lists all available music analysis presets. Each preset is a curated prompt with optimized generation parameters for a specific use case (e.g. catalog metadata enrichment, sync licensing analysis, audience profiling). Requires authentication via API key or Bearer token.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "responses": { + "200": { + "description": "Presets listed successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ] + }, + "presets": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Preset identifier to pass in the analyze request" + }, + "label": { + "type": "string", + "description": "Human-readable preset name" + }, + "description": { + "type": "string", + "description": "What this preset does" + }, + "requiresAudio": { + "type": "boolean", + "description": "Whether this preset needs an audio_url" + }, + "responseFormat": { + "type": "string", + "enum": [ + "json", + "text" + ], + "description": "Expected response format" + } + } + } + } + } + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key / Bearer token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SongAnalyzeErrorResponse" + } + } + } + } + } + } + }, + "/api/songs/analyze": { + "post": { + "description": "Analyze music using a state-of-the-art Audio Language Model that listens directly to the audio waveform. Unlike text-based AI, this model processes the actual sound — identifying harmony, structure, timbre, lyrics, and cultural context through deep music understanding. Supports audio up to 20 minutes (MP3, WAV, FLAC). Two modes: (1) **Presets** — pass a `preset` name like `catalog_metadata`, `mood_tags`, or `full_report` for structured, optimized output. (2) **Custom prompt** — pass a `prompt` for free-form questions. The `full_report` preset runs all 13 presets in parallel and returns a comprehensive music intelligence report. Use `GET /api/songs/analyze/presets` to list available presets.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Music analysis request", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SongAnalyzeRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Music analysis completed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SongAnalyzeResponse" + } + } + } + }, + "400": { + "description": "Bad request — missing or invalid fields", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SongAnalyzeErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — invalid or missing API key / Bearer token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SongAnalyzeErrorResponse" + } + } + } + }, + "500": { + "description": "Server error — upstream model unavailable or inference failed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SongAnalyzeErrorResponse" + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer" + }, + "apiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "x-api-key", + "description": "Your Recoup API key. [Learn more](/quickstart#api-keys)." + } + }, + "schemas": { + "AddCatalogSongInput": { + "type": "object", + "required": [ + "catalog_id", + "isrc" + ], + "properties": { + "catalog_id": { + "type": "string", + "format": "uuid", + "description": "Catalog ID to which the song will be added" + }, + "isrc": { + "type": "string", + "description": "Song ISRC to associate to the catalog" + }, + "name": { + "type": "string", + "description": "Optional. Applied only if internal search cannot find valid info for ISRC" + }, + "album": { + "type": "string", + "description": "Optional. Applied only if internal search cannot find valid info for ISRC" + }, + "notes": { + "type": "string", + "description": "Optional. Applied only if internal search cannot find valid info for ISRC" + }, + "artists": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional array of artist names. Applied only if internal search lacks info" + } + } + }, + "AddCatalogSongsRequest": { + "type": "object", + "required": [ + "songs" + ], + "properties": { + "songs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AddCatalogSongInput" + }, + "description": "Array of songs for batch updates" + } + } + }, + "ApifyRunResult": { + "type": "object", + "properties": { + "runId": { + "type": "string", + "description": "Unique identifier for the Apify run" + }, + "datasetId": { + "type": "string", + "description": "Unique identifier for the dataset containing scraped data" + }, + "error": { + "type": "string", + "nullable": true, + "description": "Error message if the run failed (null if successful)" + } + } + }, + "Artist": { + "type": "object", + "properties": { + "account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the artist account" + }, + "name": { + "type": "string", + "description": "Artist display name" + }, + "image": { + "type": "string", + "nullable": true, + "description": "Artist profile image URL" + }, + "pinned": { + "type": "boolean", + "description": "Whether the account has pinned this artist" + }, + "socials": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ArtistSocial" + }, + "description": "Social media profiles linked to the artist" + } + } + }, + "ArtistFan": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the fan's social profile" + }, + "username": { + "type": "string", + "description": "Username or handle on the platform" + }, + "avatar": { + "type": "string", + "description": "URL to the fan's avatar/profile image" + }, + "profile_url": { + "type": "string", + "description": "Full URL to the fan's profile on the platform" + }, + "region": { + "type": "string", + "description": "Geographic region or location of the fan" + }, + "bio": { + "type": "string", + "description": "Fan's biography or profile description" + }, + "followerCount": { + "type": "integer", + "description": "Number of followers the fan has" + }, + "followingCount": { + "type": "integer", + "description": "Number of accounts the fan is following" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of when the fan data was last updated" + } + } + }, + "ArtistFansErrorResponse": { + "type": "object", + "required": [ + "status", + "error" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "ArtistFansPagination": { + "type": "object", + "properties": { + "total_count": { + "type": "integer", + "description": "Total number of records available" + }, + "page": { + "type": "integer", + "description": "Current page number" + }, + "limit": { + "type": "integer", + "description": "Number of records per page" + }, + "total_pages": { + "type": "integer", + "description": "Total number of pages available" + } + } + }, + "ArtistFansResponse": { + "type": "object", + "required": [ + "status", + "fans", + "pagination" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "fans": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ArtistFan" + }, + "description": "List of social profiles from fans across all platforms" + }, + "pagination": { + "$ref": "#/components/schemas/ArtistFansPagination", + "description": "Pagination metadata for the response" + } + } + }, + "ArtistProfile": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the artist" + }, + "profiles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ArtistProfileSocialProfile" + }, + "description": "List of social media profiles" + }, + "total_followers": { + "type": "integer", + "description": "Sum of followers across all platforms" + }, + "total_following": { + "type": "integer", + "description": "Sum of following across all platforms" + }, + "total_posts": { + "type": "integer", + "description": "Sum of posts across all platforms" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of when the data was last updated" + } + } + }, + "ArtistProfileErrorResponse": { + "type": "object", + "required": [ + "status", + "message" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "message": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "ArtistProfileResponse": { + "type": "object", + "required": [ + "status", + "profile" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "profile": { + "$ref": "#/components/schemas/ArtistProfile", + "description": "The artist's comprehensive profile information" + } + } + }, + "ArtistProfileSocialProfile": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the social profile" + }, + "username": { + "type": "string", + "description": "Username on the platform" + }, + "profile_url": { + "type": "string", + "description": "Direct URL to the profile" + }, + "avatar": { + "type": "string", + "nullable": true, + "description": "URL to the profile avatar image" + }, + "bio": { + "type": "string", + "nullable": true, + "description": "Profile biography or description" + }, + "follower_count": { + "type": "integer", + "nullable": true, + "description": "Number of followers on this platform" + }, + "following_count": { + "type": "integer", + "nullable": true, + "description": "Number of accounts followed on this platform" + }, + "post_count": { + "type": "integer", + "nullable": true, + "description": "Number of posts on this platform" + }, + "region": { + "type": "string", + "nullable": true, + "description": "Geographic region of the profile" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of when the profile was last updated" + } + } + }, + "ArtistSegment": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the artist_segments record" + }, + "artist_account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the artist's accounts record" + }, + "segment_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the segments record" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of when the segment data was last updated" + }, + "segment_name": { + "type": "string", + "description": "Name of the segment (e.g., 'Twitter Followers')" + }, + "artist_name": { + "type": "string", + "description": "Name of the artist" + } + } + }, + "ArtistSegmentsErrorResponse": { + "type": "object", + "required": [ + "status", + "message" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "message": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "ArtistSegmentsPagination": { + "type": "object", + "properties": { + "total_count": { + "type": "integer", + "description": "Total number of segments available" + }, + "page": { + "type": "integer", + "description": "Current page number" + }, + "limit": { + "type": "integer", + "description": "Number of segments per page" + }, + "total_pages": { + "type": "integer", + "description": "Total number of pages available" + } + } + }, + "ArtistSegmentsResponse": { + "type": "object", + "required": [ + "status", + "segments", + "pagination" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "segments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ArtistSegment" + }, + "description": "List of segment objects associated with the artist" + }, + "pagination": { + "$ref": "#/components/schemas/ArtistSegmentsPagination", + "description": "Pagination metadata for the response" + } + } + }, + "ArtistSocial": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the social profile" + }, + "platform": { + "type": "string", + "description": "Social media platform (e.g., instagram, twitter, tiktok)" + }, + "username": { + "type": "string", + "description": "Username on the platform" + }, + "profile_url": { + "type": "string", + "description": "Full URL to the social media profile" + } + } + }, + "ArtistSocialsErrorResponse": { + "type": "object", + "required": [ + "status", + "message" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "message": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "ArtistSocialsPagination": { + "type": "object", + "properties": { + "total_count": { + "type": "integer", + "description": "Total number of social profiles available" + }, + "page": { + "type": "integer", + "description": "Current page number" + }, + "limit": { + "type": "integer", + "description": "Number of social profiles per page" + }, + "total_pages": { + "type": "integer", + "description": "Total number of pages available" + } + } + }, + "ArtistSocialsResponse": { + "type": "object", + "required": [ + "status", + "socials", + "pagination" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "socials": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SocialProfile" + }, + "description": "List of social media profiles associated with the artist" + }, + "pagination": { + "$ref": "#/components/schemas/ArtistSocialsPagination", + "description": "Pagination metadata for the response" + } + } + }, + "ArtistSocialsScrapeRequest": { + "type": "object", + "required": [ + "artist_account_id" + ], + "properties": { + "artist_account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the artist account to scrape socials for", + "example": "1873859c-dd37-4e9a-9bac-80d35a1b2c3d" + } + } + }, + "ArtistSocialsScrapeResponse": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ApifyRunResult" + }, + "description": "Array of Apify run results, one for each social profile scraped" + }, + "ArtistsErrorResponse": { + "type": "object", + "required": [ + "status", + "message" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "message": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "ArtistsResponse": { + "type": "object", + "required": [ + "status", + "artists" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ], + "description": "Status of the request" + }, + "artists": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Artist" + }, + "description": "List of artist objects" + }, + "message": { + "type": "string", + "description": "Error message (only present if status is error)" + } + } + }, + "Catalog": { + "type": "object", + "description": "A catalog with its metadata", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the catalog" + }, + "name": { + "type": "string", + "description": "Name of the catalog" + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of when the catalog was created" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of when the catalog was last updated" + } + } + }, + "CatalogSong": { + "type": "object", + "description": "A song within a catalog with its metadata and associated artists", + "properties": { + "catalog_id": { + "type": "string", + "format": "uuid", + "description": "Catalog ID this song entry is associated with" + }, + "isrc": { + "type": "string", + "description": "International Standard Recording Code (primary key)" + }, + "name": { + "type": "string", + "description": "Name of the song" + }, + "album": { + "type": "string", + "description": "Name of the album the song belongs to" + }, + "lyrics": { + "type": "string", + "description": "Full lyrics of the song" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of when the song data was last updated" + }, + "artists": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SongArtist" + }, + "description": "Array of artist objects associated with this song" + } + } + }, + "CatalogSongsErrorResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "CatalogSongsPagination": { + "type": "object", + "description": "Pagination metadata for catalog songs response", + "properties": { + "total_count": { + "type": "integer", + "description": "Total number of songs in the catalog" + }, + "page": { + "type": "integer", + "description": "Current page number" + }, + "limit": { + "type": "integer", + "description": "Number of songs per page" + }, + "total_pages": { + "type": "integer", + "description": "Total number of pages available" + } + } + }, + "CatalogSongsResponse": { + "type": "object", + "description": "Response containing catalog songs data with pagination", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ], + "description": "Status of the request" + }, + "songs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CatalogSong" + }, + "description": "Array of song objects with artist information" + }, + "pagination": { + "$ref": "#/components/schemas/CatalogSongsPagination", + "description": "Pagination metadata for the response" + }, + "error": { + "type": "string", + "description": "Error message (only present if status is 'error')" + } + } + }, + "CatalogsErrorResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "CatalogsResponse": { + "type": "object", + "description": "Response containing catalogs data", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ], + "description": "Status of the request" + }, + "catalogs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Catalog" + }, + "description": "Array of catalog objects" + }, + "error": { + "type": "string", + "description": "Error message (only present if status is 'error')" + } + } + }, + "CreateArtistError": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "missing_fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of missing or invalid field names" + }, + "error": { + "type": "string", + "description": "Error message describing the validation failure" + }, + "message": { + "type": "string", + "description": "Error message (for invalid JSON or other errors)" + } + } + }, + "CreateArtistRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "description": "The name of the artist to create" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the account to create the artist for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, the artist is created for the API key's own account." + }, + "organization_id": { + "type": "string", + "format": "uuid", + "description": "Optional organization ID to link the new artist to" + } + } + }, + "CreateArtistResponse": { + "type": "object", + "required": [ + "artist" + ], + "properties": { + "artist": { + "$ref": "#/components/schemas/CreatedArtist" + } + } + }, + "CreateCatalogInput": { + "type": "object", + "required": [ + "account_id" + ], + "properties": { + "account_id": { + "type": "string", + "format": "uuid", + "description": "The account to associate the catalog with" + }, + "name": { + "type": "string", + "description": "Catalog name to create if catalog_id is omitted" + }, + "catalog_id": { + "type": "string", + "format": "uuid", + "description": "Existing catalog ID to link to the account" + } + } + }, + "CreateCatalogsRequest": { + "type": "object", + "required": [ + "catalogs" + ], + "properties": { + "catalogs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CreateCatalogInput" + }, + "description": "Array of catalog inputs for bulk create/link operations" + } + } + }, + "CreateSongInput": { + "type": "object", + "required": [ + "isrc" + ], + "properties": { + "isrc": { + "type": "string", + "description": "International Standard Recording Code of the song to create or fetch" + }, + "name": { + "type": "string", + "description": "Optional. Song name, applied only if internal search cannot find valid info" + }, + "album": { + "type": "string", + "description": "Optional. Album name, applied only if internal search cannot find valid info" + }, + "notes": { + "type": "string", + "description": "Optional. Notes for the song, applied only if internal search cannot find valid info" + }, + "artists": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional array of artist names, applied only if internal search cannot find valid info" + } + } + }, + "CreateSongsRequest": { + "type": "object", + "required": [ + "songs" + ], + "properties": { + "songs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CreateSongInput" + }, + "description": "Array of song inputs for bulk create/fetch" + } + } + }, + "CreateTaskRequest": { + "type": "object", + "required": [ + "title", + "prompt", + "schedule", + "account_id", + "artist_account_id" + ], + "properties": { + "title": { + "type": "string", + "description": "Descriptive title of the task", + "example": "Weekly Genre Pulse Check" + }, + "prompt": { + "type": "string", + "description": "Instruction/prompt executed by the task", + "example": "Execute this weekly genre analysis workflow and email a summary to the team." + }, + "schedule": { + "type": "string", + "description": "Cron expression defining when the task runs (e.g., '0 9 * * 4' for Thursdays at 9 AM)", + "example": "0 9 * * 4" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the associated account", + "example": "848cd58d-700f-4b38-ab4c-d9f52a1b2c3d" + }, + "artist_account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the associated artist account", + "example": "1873859c-dd37-4e9a-9bac-80d35a1b2c3d" + } + } + }, + "CreatedArtist": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the created artist account" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the artist account (same as id)" + }, + "name": { + "type": "string", + "description": "Name of the artist" + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "description": "ISO timestamp of when the artist was created" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "description": "ISO timestamp of when the artist was last updated" + }, + "image": { + "type": "string", + "nullable": true, + "description": "Artist profile image URL" + }, + "instruction": { + "type": "string", + "nullable": true, + "description": "Custom AI instruction for this artist" + }, + "knowledges": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "description": "Knowledge base references for this artist" + }, + "label": { + "type": "string", + "nullable": true, + "description": "Record label name" + }, + "organization": { + "type": "string", + "nullable": true, + "description": "Organization name" + }, + "company_name": { + "type": "string", + "nullable": true, + "description": "Company name" + }, + "job_title": { + "type": "string", + "nullable": true, + "description": "Job title" + }, + "role_type": { + "type": "string", + "nullable": true, + "description": "Role type" + }, + "onboarding_status": { + "type": "string", + "nullable": true, + "description": "Onboarding status" + }, + "onboarding_data": { + "nullable": true, + "description": "Onboarding data" + }, + "account_info": { + "type": "array", + "description": "Account info records" + }, + "account_socials": { + "type": "array", + "description": "Linked social media accounts" + } + } + }, + "DeleteCatalogInput": { + "type": "object", + "required": [ + "catalog_id", + "account_id" + ], + "properties": { + "catalog_id": { + "type": "string", + "format": "uuid", + "description": "Catalog ID to remove" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "Account ID whose relationship will be removed" + } + } + }, + "DeleteCatalogSongInput": { + "type": "object", + "required": [ + "catalog_id", + "isrc" + ], + "properties": { + "catalog_id": { + "type": "string", + "format": "uuid", + "description": "Catalog ID from which the song will be removed" + }, + "isrc": { + "type": "string", + "description": "Song ISRC to remove from the catalog" + } + } + }, + "DeleteCatalogSongsRequest": { + "type": "object", + "required": [ + "songs" + ], + "properties": { + "songs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DeleteCatalogSongInput" + }, + "description": "Array of songs for batch deletes" + } + } + }, + "DeleteCatalogsRequest": { + "type": "object", + "required": [ + "catalogs" + ], + "properties": { + "catalogs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DeleteCatalogInput" + }, + "description": "Array of catalog-account pairs to remove" + } + } + }, + "DeleteTaskRequest": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the task to delete", + "example": "aade2bce-55c7-468e-a606-c4e76fb2ea2a" + } + } + }, + "DeleteTaskResponse": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ], + "description": "Status of the delete operation" + }, + "error": { + "type": "string", + "description": "Error message (only present if status is error)" + } + } + }, + "Error": { + "required": [ + "error", + "message" + ], + "type": "object", + "properties": { + "error": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + }, + "SegmentFan": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the fan_segments record" + }, + "username": { + "type": "string", + "description": "Username or handle on the platform" + }, + "avatar": { + "type": "string", + "description": "URL to the fan's avatar/profile image" + }, + "profile_url": { + "type": "string", + "description": "Full URL to the fan's profile on the platform" + }, + "segment_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the fan's segments record" + }, + "segment_name": { + "type": "string", + "description": "Name of the segment (e.g., 'Twitter Followers')" + }, + "fan_social_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the fan's socials media profile account" + }, + "region": { + "type": "string", + "description": "Geographic region or location of the fan" + }, + "bio": { + "type": "string", + "description": "Fan's biography or profile description" + }, + "follower_count": { + "type": "integer", + "description": "Number of followers the fan has" + }, + "following_count": { + "type": "integer", + "description": "Number of accounts the fan is following" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of when the fan data was last updated" + } + } + }, + "SegmentFansErrorResponse": { + "type": "object", + "required": [ + "status", + "error" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "SegmentFansPagination": { + "type": "object", + "properties": { + "total_count": { + "type": "integer", + "description": "Total number of records available" + }, + "page": { + "type": "integer", + "description": "Current page number" + }, + "limit": { + "type": "integer", + "description": "Number of records per page" + }, + "total_pages": { + "type": "integer", + "description": "Total number of pages available" + } + } + }, + "SegmentFansResponse": { + "type": "object", + "required": [ + "status", + "fans", + "pagination" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "fans": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SegmentFan" + }, + "description": "List of social profiles from fans in the segment" + }, + "pagination": { + "$ref": "#/components/schemas/SegmentFansPagination", + "description": "Pagination metadata for the response" + } + } + }, + "SocialProfile": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the artist's account_socials record" + }, + "social_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the artist's socials account" + }, + "username": { + "type": "string", + "description": "Username on the platform" + }, + "profile_url": { + "type": "string", + "description": "Direct URL to the profile" + }, + "avatar": { + "type": "string", + "nullable": true, + "description": "URL to the profile avatar image" + }, + "bio": { + "type": "string", + "nullable": true, + "description": "Profile biography or description" + }, + "follower_count": { + "type": "integer", + "nullable": true, + "description": "Number of followers on this platform" + }, + "following_count": { + "type": "integer", + "nullable": true, + "description": "Number of accounts followed on this platform" + }, + "region": { + "type": "string", + "nullable": true, + "description": "Geographic region of the profile" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of when the profile was last updated" + } + } + }, + "Song": { + "type": "object", + "description": "A song with its metadata and associated artists", + "properties": { + "isrc": { + "type": "string", + "description": "International Standard Recording Code (primary key)" + }, + "name": { + "type": "string", + "description": "Name of the song" + }, + "album": { + "type": "string", + "description": "Name of the album the song belongs to" + }, + "notes": { + "type": "string", + "description": "Notes for the song" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of when the song data was last updated" + }, + "artists": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SongArtist" + }, + "description": "Array of artist objects associated with this song" + } + } + }, + "SongAnalyzeErrorResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Error status" + }, + "missing_fields": { + "type": "array", + "description": "Path to the first invalid or missing field when validation fails", + "items": { + "type": "string" + } + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "SongAnalyzeRequest": { + "type": "object", + "description": "Provide exactly one of `preset` or `prompt`. Use `preset` for structured analysis workflows, or `prompt` for free-form questions.", + "properties": { + "preset": { + "type": "string", + "enum": [ + "catalog_metadata", + "mood_tags", + "lyric_transcription", + "mix_feedback", + "song_description", + "music_theory", + "similar_artists", + "sample_detection", + "sync_brief_match", + "audience_profile", + "content_advisory", + "playlist_pitch", + "artist_development_notes", + "full_report" + ], + "description": "Name of a curated analysis preset. Use instead of prompt for structured, optimized output. The 'full_report' preset runs all 13 presets in parallel and returns a comprehensive report. See [List Analyze Presets](/api-reference/songs/analyze-presets) for the full list of available presets.", + "example": "catalog_metadata" + }, + "prompt": { + "type": "string", + "minLength": 1, + "maxLength": 24000, + "description": "Text prompt or question about the music", + "example": "Describe the genre, tempo, and mood of this track." + }, + "audio_url": { + "type": "string", + "format": "uri", + "description": "Public URL to an audio file (MP3, WAV, or FLAC — up to 20 minutes)", + "example": "https://example.com/song.mp3" + }, + "max_new_tokens": { + "type": "integer", + "minimum": 1, + "maximum": 2048, + "default": 512, + "description": "Maximum number of tokens to generate", + "example": 512 + }, + "temperature": { + "type": "number", + "minimum": 0, + "maximum": 2, + "default": 1, + "description": "Controls output creativity — higher values produce more varied responses", + "example": 0.7 + }, + "top_p": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 1, + "description": "Nucleus sampling probability cutoff", + "example": 0.9 + }, + "do_sample": { + "type": "boolean", + "default": false, + "description": "Enable sampling (set true when using temperature or top_p)", + "example": false + } + } + }, + "SongAnalyzeResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Request status" + }, + "preset": { + "type": "string", + "description": "Preset used for analysis, when applicable", + "example": "catalog_metadata" + }, + "response": { + "description": "Model output for single-preset or custom-prompt analysis. May be plain text or structured JSON depending on the preset." + }, + "report": { + "type": "object", + "description": "Full report payload returned only when using the `full_report` preset" + }, + "elapsed_seconds": { + "type": "number", + "format": "float", + "description": "Inference time in seconds" + } + } + }, + "SongArtist": { + "type": "object", + "description": "Artist associated with a song", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the artist account" + }, + "name": { + "type": "string", + "nullable": true, + "description": "Name of the artist (can be null)" + }, + "timestamp": { + "type": "integer", + "nullable": true, + "description": "Timestamp associated with the artist account (can be null)" + } + } + }, + "SongsErrorResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "SongsResponse": { + "type": "object", + "description": "Response containing songs data", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ], + "description": "Status of the request" + }, + "songs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Song" + }, + "description": "Array of song objects with artist information" + }, + "error": { + "type": "string", + "description": "Error message (only present if status is 'error')" + } + } + }, + "Task": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the task" + }, + "title": { + "type": "string", + "description": "Descriptive title or name of the task" + }, + "prompt": { + "type": "string", + "description": "Detailed instruction or prompt for task execution" + }, + "schedule": { + "type": "string", + "description": "Cron expression defining when the task should execute (e.g., '0 10 * * *')" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the associated account" + }, + "artist_account_id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the associated artist account" + }, + "enabled": { + "type": "boolean", + "nullable": true, + "description": "Whether the task is enabled. Defaults to true." + }, + "trigger_schedule_id": { + "type": "string", + "nullable": true, + "description": "Identifier for the trigger schedule associated with this task" + }, + "recent_runs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TaskRunResponse" + }, + "description": "Last 5 runs for this task, sourced from the Trigger.dev API." + }, + "upcoming": { + "type": "array", + "items": { + "type": "string", + "format": "date-time" + }, + "description": "Next scheduled run times, sourced from the latest Trigger.dev run payload." + } + } + }, + "TaskRunListResponse": { + "type": "object", + "required": [ + "status", + "runs" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Indicates the request was successful" + }, + "runs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TaskRunResponse" + }, + "description": "List of recent task runs for the authenticated account. Each item is a raw Trigger.dev SDK run object (same shape as TaskRunResponse, but without `output` and `error` fields)." + } + } + }, + "TaskRunResponse": { + "type": "object", + "description": "Raw Trigger.dev SDK run object. The API passes through the SDK response without field mapping. See https://trigger.dev/docs/management/runs/retrieve for the full reference. When listing runs, `output`, `error`, `payload`, and `attempts` are not included.", + "required": [ + "id", + "status", + "taskIdentifier", + "createdAt", + "updatedAt" + ], + "properties": { + "id": { + "type": "string", + "description": "The unique run identifier, prefixed with `run_`" + }, + "status": { + "type": "string", + "enum": [ + "PENDING_VERSION", + "DELAYED", + "QUEUED", + "EXECUTING", + "REATTEMPTING", + "FROZEN", + "COMPLETED", + "CANCELED", + "FAILED", + "CRASHED", + "INTERRUPTED", + "SYSTEM_FAILURE" + ], + "description": "Current run status" + }, + "taskIdentifier": { + "type": "string", + "description": "The task type identifier (e.g. 'setup-sandbox', 'run-sandbox-command')" + }, + "idempotencyKey": { + "type": "string", + "nullable": true, + "description": "Idempotency key used to deduplicate trigger requests" + }, + "version": { + "type": "string", + "description": "The worker version that executed the run" + }, + "isTest": { + "type": "boolean", + "description": "Whether this is a test run" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "When the run was created (ISO 8601)" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "When the run was last updated (ISO 8601)" + }, + "startedAt": { + "type": "string", + "format": "date-time", + "nullable": true, + "description": "When execution started (null if not yet started)" + }, + "finishedAt": { + "type": "string", + "format": "date-time", + "nullable": true, + "description": "When the run finished (null if still running)" + }, + "delayedUntil": { + "type": "string", + "format": "date-time", + "nullable": true, + "description": "If delayed, when the run becomes eligible to execute" + }, + "ttl": { + "description": "Time-to-live. If the run is not started within this duration, it expires.", + "nullable": true + }, + "expiredAt": { + "type": "string", + "format": "date-time", + "nullable": true, + "description": "When the run expired (null if not expired)" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Tags associated with this run (max 10)" + }, + "metadata": { + "type": "object", + "nullable": true, + "description": "JSON metadata attached to the run" + }, + "costInCents": { + "type": "number", + "description": "Compute cost of the run in cents" + }, + "baseCostInCents": { + "type": "number", + "description": "Base invocation cost in cents" + }, + "durationMs": { + "type": "number", + "description": "Compute duration in milliseconds" + }, + "env": { + "type": "object", + "description": "Environment the run executed in", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "user": { + "type": "string", + "nullable": true + } + } + }, + "depth": { + "type": "integer", + "description": "Nesting depth for child runs" + }, + "batchId": { + "type": "string", + "nullable": true, + "description": "Batch ID if triggered as part of a batch" + }, + "triggerFunction": { + "type": "string", + "enum": [ + "trigger", + "triggerAndWait", + "batchTrigger", + "batchTriggerAndWait" + ], + "description": "The function used to trigger this run" + }, + "payload": { + "description": "Input payload for the task. Only present when retrieving by runId.", + "nullable": true + }, + "output": { + "description": "Task output data. Only present when retrieving by runId.", + "nullable": true + }, + "error": { + "type": "object", + "nullable": true, + "description": "Error details if the run failed. Only present when retrieving by runId.", + "properties": { + "message": { + "type": "string", + "description": "Human-readable error message" + }, + "name": { + "type": "string", + "description": "Error name or type" + }, + "stackTrace": { + "type": "string", + "description": "Stack trace" + } + } + }, + "attempts": { + "type": "array", + "description": "Attempt history. Only present when retrieving by runId.", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Attempt ID, prefixed with `attempt_`" + }, + "status": { + "type": "string", + "enum": [ + "PENDING", + "EXECUTING", + "PAUSED", + "COMPLETED", + "FAILED", + "CANCELED" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "startedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "completedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "error": { + "type": "object", + "nullable": true, + "properties": { + "message": { + "type": "string" + }, + "name": { + "type": "string" + }, + "stackTrace": { + "type": "string" + } + } + } + } + } + }, + "schedule": { + "type": "object", + "nullable": true, + "description": "Schedule information if triggered by a schedule. Only present when retrieving by runId." + }, + "relatedRuns": { + "type": "object", + "nullable": true, + "description": "Related run references (root, parent, children). Only present when retrieving by runId." + } + } + }, + "TasksResponse": { + "type": "object", + "required": [ + "status", + "tasks" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ], + "description": "Status of the request" + }, + "tasks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Task" + }, + "description": "Array of task objects" + }, + "error": { + "type": "string", + "description": "Error message (only present if status is error)" + } + } + }, + "UpdateTaskRequest": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the task to update", + "example": "aade2bce-55c7-468e-a606-c4e76fb2ea2a" + }, + "title": { + "type": "string", + "description": "New descriptive title of the task", + "example": "Weekly Genre Pulse Check (Updated)" + }, + "prompt": { + "type": "string", + "description": "New instruction/prompt executed by the task", + "example": "Execute this weekly genre analysis workflow and email a summary to the team." + }, + "schedule": { + "type": "string", + "description": "New cron expression defining when the task runs", + "example": "0 10 * * 4" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "New UUID of the associated account", + "example": "848cd58d-700f-4b38-ab4c-d9f52a1b2c3d" + }, + "artist_account_id": { + "type": "string", + "format": "uuid", + "description": "New UUID of the associated artist account", + "example": "1873859c-dd37-4e9a-9bac-80d35a1b2c3d" + }, + "enabled": { + "type": "boolean", + "nullable": true, + "description": "Whether the task is enabled. Can be true, false, or null.", + "example": true + } + } + } + } + } +} diff --git a/api-reference/openapi/research.json b/api-reference/openapi/research.json new file mode 100644 index 0000000..ccf617b --- /dev/null +++ b/api-reference/openapi/research.json @@ -0,0 +1,3968 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Recoup API - Research", + "description": "API documentation for the Recoup platform - an AI agent platform for the music industry", + "license": { + "name": "MIT" + }, + "version": "1.0.0" + }, + "servers": [ + { + "url": "https://recoup-api.vercel.app" + } + ], + "paths": { + "/api/chats": { + "get": { + "description": "Retrieve chat rooms (conversations) for the authenticated account. If the account has access to organizations, pass account_id to filter to a specific account within those organizations. Optionally filter by an artist_account_id. The endpoint returns metadata about each room, including the topic, associated artist, and last updated timestamp.", + "parameters": [ + { + "name": "artist_account_id", + "in": "query", + "description": "Optional. Filter chats to only include those for the specified artist.", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "account_id", + "in": "query", + "description": "Filter to a specific account. Only applicable when the authenticated account has access to multiple accounts via organization membership.", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Chats retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChatsResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid query parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChatsErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden - account_id is not a member of the organization or account tried to filter by an account_id they don't have access to", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "post": { + "description": "Create a new chat room. Optionally associate it with an artist and/or provide a client-generated chat ID. Pass accountId to create a chat on behalf of a specific account the API key has access to.", + "requestBody": { + "description": "Chat creation parameters", + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateChatRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Chat created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateChatResponse" + } + } + } + }, + "400": { + "description": "Bad request - failed to create chat", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateChatErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - API key does not have access to the specified accountId", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateChatErrorResponse" + } + } + } + } + } + }, + "patch": { + "description": "Update a chat room's topic (display name). The chatId is required; the topic field will be updated. Topic must be between 3 and 50 characters.", + "requestBody": { + "description": "Chat fields to update", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateChatRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Chat updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateChatResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid parameters or validation error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateChatErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden - API key does not have access to this chat", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not found - chat room does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateChatErrorResponse" + } + } + } + } + } + }, + "delete": { + "description": "Delete a chat room by ID. This operation also removes related room records (memory emails, memories, room-report links, and segment-room links) before deleting the room itself.", + "requestBody": { + "description": "Chat deletion parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteChatRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Chat deleted successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteChatResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid parameters or validation error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteChatErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden - API key does not have access to this chat", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not found - chat room does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteChatErrorResponse" + } + } + } + }, + "500": { + "description": "Server error - failed to delete chat", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteChatErrorResponse" + } + } + } + } + } + } + }, + "/api/chats/{id}/artist": { + "get": { + "description": "Retrieve the artist associated with a specific chat room. Returns 404 if the chat does not exist or is not accessible by the authenticated caller.", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The unique identifier (UUID) of the chat room.", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Chat artist resolved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChatArtistResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid chat id", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChatArtistErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not found - chat does not exist or is not accessible", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChatArtistErrorResponse" + } + } + } + } + } + } + }, + "/api/chats/{id}/segment": { + "get": { + "description": "Retrieve the segment associated with a specific chat room. Returns 404 if the chat does not exist or is not accessible by the authenticated caller.", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The unique identifier (UUID) of the chat room.", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Chat segment resolved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChatSegmentResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid chat id", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChatSegmentErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not found - chat does not exist or is not accessible", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChatSegmentErrorResponse" + } + } + } + } + } + } + }, + "/api/chats/{id}/messages": { + "get": { + "description": "Retrieve all messages (memories) for a specific chat room in chronological order.", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The unique identifier (UUID) of the chat room.", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Messages retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChatMessagesResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid chat id", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChatMessagesErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden - caller does not have access to this chat", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not found - chat does not exist or is not accessible", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChatMessagesErrorResponse" + } + } + } + }, + "500": { + "description": "Server error - failed to retrieve messages", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChatMessagesErrorResponse" + } + } + } + } + } + } + }, + "/api/chats/{id}/messages/copy": { + "post": { + "description": "Copy all messages from the source chat (`id` path param) to a target chat (`targetChatId` in request body). By default, existing target messages are cleared before copy.", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The source chat room UUID.", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "Copy target options", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CopyChatMessagesRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Messages copied successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CopyChatMessagesResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid payload or chat identifiers", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CopyChatMessagesErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden - caller lacks access to source or target chat", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CopyChatMessagesErrorResponse" + } + } + } + }, + "404": { + "description": "Not found - source or target chat does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CopyChatMessagesErrorResponse" + } + } + } + }, + "500": { + "description": "Server error - failed to copy messages", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CopyChatMessagesErrorResponse" + } + } + } + } + } + } + }, + "/api/chats/{id}/messages/trailing": { + "delete": { + "description": "Delete all messages in a chat from a given message onward (inclusive), identified by `from_message_id`.", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The unique identifier (UUID) of the chat room.", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "from_message_id", + "in": "query", + "description": "The message UUID from which trailing messages should be deleted (inclusive).", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Trailing messages deleted successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteTrailingChatMessagesResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid or missing query/path parameters or message does not belong to chat", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteTrailingChatMessagesErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteTrailingChatMessagesErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - access denied to this chat", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteTrailingChatMessagesErrorResponse" + } + } + } + }, + "404": { + "description": "Not found - chat or message does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteTrailingChatMessagesErrorResponse" + } + } + } + }, + "500": { + "description": "Server error - failed to delete trailing messages", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteTrailingChatMessagesErrorResponse" + } + } + } + } + } + } + }, + "/api/chats/compact": { + "post": { + "description": "Compact one or more chat conversations into summarized versions. This reduces the size of chat history while preserving key information. Optionally provide a prompt to control what information gets preserved in the compacted summary.", + "requestBody": { + "description": "Chat compaction parameters", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CompactChatsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Chats compacted successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CompactChatsResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not found - one or more chat IDs do not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api/chat/generate": { + "post": { + "servers": [ + { + "url": "https://recoup-api.vercel.app" + } + ], + "description": "Generate AI-powered text responses using the Recoup chat system. This endpoint processes chat requests and returns generated text along with metadata about the generation process.", + "security": [ + { + "apiKeyAuth": [] + } + ], + "requestBody": { + "description": "Chat generation request", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatGenerateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Chat generated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatGenerateResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatGenerateErrorResponse" + } + } + } + } + } + } + }, + "/api/chat": { + "post": { + "servers": [ + { + "url": "https://recoup-api.vercel.app" + } + ], + "description": "Stream AI-powered chat responses using the Recoup chat system. This endpoint mirrors the request payload of the Chat Generate API but returns a streaming response compatible with the Vercel AI SDK `createUIMessageStreamResponse`. The stream emits UI message parts encoded as data chunks that can be parsed with `createUIMessageStreamParser`.", + "security": [ + { + "apiKeyAuth": [] + } + ], + "requestBody": { + "description": "Chat stream request", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatStreamRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Streaming response with UI message parts. Events include: message-start (assistant begins message), message-delta (incremental updates), message-end (assistant finishes message), error (stream error), and metadata (usage data).", + "content": { + "text/event-stream": { + "schema": { + "type": "string", + "description": "Server-Sent Events stream containing UI message parts" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatStreamErrorResponse" + } + } + } + } + } + } + }, + "/api/research": { + "get": { + "description": "Search for artists by name. Returns matching results with profile summaries.", + "parameters": [ + { + "name": "q", + "in": "query", + "required": true, + "description": "Artist name to search for.", + "schema": { + "type": "string" + } + }, + { + "name": "type", + "in": "query", + "required": false, + "description": "Entity type.", + "schema": { + "type": "string", + "enum": [ + "artists", + "tracks", + "albums", + "playlists", + "curators", + "stations" + ], + "default": "artists" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "Maximum number of results.", + "schema": { + "type": "integer", + "default": 10 + } + } + ], + "responses": { + "200": { + "description": "Search results", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchSearchResponse" + } + } + } + } + } + } + }, + "/api/research/albums": { + "get": { + "description": "Get an artist's full discography — albums, EPs, and singles with release dates.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID (UUID).", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Artist albums", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchAlbumsResponse" + } + } + } + } + } + } + }, + "/api/research/audience": { + "get": { + "description": "Get audience demographics for an artist on a specific platform — age, gender, and country breakdown.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID (UUID).", + "schema": { + "type": "string" + } + }, + { + "name": "platform", + "in": "query", + "required": false, + "description": "Platform to get demographics for. Defaults to instagram.", + "schema": { + "type": "string", + "enum": [ + "instagram", + "tiktok", + "youtube" + ], + "default": "instagram" + } + } + ], + "responses": { + "200": { + "description": "Audience demographics", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchAudienceResponse" + } + } + } + } + } + } + }, + "/api/research/career": { + "get": { + "description": "Get an artist's career timeline — key milestones, trajectory, and career stage.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID (UUID).", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Career timeline", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchCareerResponse" + } + } + } + } + } + } + }, + "/api/research/charts": { + "get": { + "description": "Get global chart positions for a platform — Spotify, Apple Music, TikTok, YouTube, iTunes, Shazam, etc. NOT artist-scoped. Returns ranked entries with track and artist info.", + "parameters": [ + { + "name": "platform", + "in": "query", + "required": true, + "description": "Chart platform: spotify, applemusic, tiktok, youtube, itunes, shazam, etc.", + "schema": { + "type": "string" + } + }, + { + "name": "country", + "in": "query", + "required": false, + "description": "Two-letter country code (e.g. US, GB, DE).", + "schema": { + "type": "string" + } + }, + { + "name": "interval", + "in": "query", + "required": false, + "description": "Time interval (e.g. daily, weekly).", + "schema": { + "type": "string" + } + }, + { + "name": "type", + "in": "query", + "required": false, + "description": "Chart type (varies by platform).", + "schema": { + "type": "string" + } + }, + { + "name": "latest", + "in": "query", + "required": false, + "description": "Return only the latest chart.", + "schema": { + "type": "string", + "default": "true" + } + } + ], + "responses": { + "200": { + "description": "Chart data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchChartsResponse" + } + } + } + } + } + } + }, + "/api/research/cities": { + "get": { + "description": "Get the top cities where an artist's fans listen, ranked by listener concentration.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID (UUID).", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Top listener cities", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchCitiesResponse" + } + } + } + } + } + } + }, + "/api/research/curator": { + "get": { + "description": "Get curator profile — who curates a playlist, their other playlists, and follower reach.", + "parameters": [ + { + "name": "platform", + "in": "query", + "required": true, + "schema": { + "type": "string", + "enum": [ + "spotify", + "applemusic", + "deezer", + "amazon", + "youtube" + ] + }, + "description": "Streaming platform." + }, + { + "name": "id", + "in": "query", + "required": true, + "description": "Curator ID.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Curator profile", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchCuratorResponse" + } + } + } + } + } + } + }, + "/api/research/deep": { + "post": { + "description": "Perform deep, comprehensive research on a topic. Browses multiple sources extensively and returns a cited report. Use for full artist deep dives, competitive analysis, and any research requiring synthesis across many sources.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchDeepRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Deep research report with citations", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchDeepResponse" + } + } + } + } + } + } + }, + "/api/research/discover": { + "get": { + "description": "Discover artists by criteria — filter by country, genre, Spotify monthly listener range, and sort by growth metrics.", + "parameters": [ + { + "name": "country", + "in": "query", + "required": false, + "description": "ISO country code (e.g., US, BR, GB).", + "schema": { + "type": "string" + } + }, + { + "name": "genre", + "in": "query", + "required": false, + "description": "Genre ID (use GET /api/research/genres to list).", + "schema": { + "type": "integer" + } + }, + { + "name": "sp_monthly_listeners_min", + "in": "query", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "sp_monthly_listeners_max", + "in": "query", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "sort", + "in": "query", + "required": false, + "description": "Sort field (e.g., weekly_diff.sp_monthly_listeners).", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 20 + } + } + ], + "responses": { + "200": { + "description": "Filtered artist list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchDiscoverResponse" + } + } + } + } + } + } + }, + "/api/research/enrich": { + "post": { + "description": "Enrich an entity with structured data from web research. Provide a description of who or what to research and a JSON schema defining the fields to extract. Returns typed data with citations.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchEnrichRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Structured enrichment data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchEnrichResponse" + } + } + } + } + } + } + }, + "/api/research/extract": { + "post": { + "description": "Extract clean markdown content from one or more public URLs. Handles JavaScript-heavy pages and PDFs. Returns focused excerpts aligned to an objective, or full page content.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchExtractRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Extracted content from URLs", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchExtractResponse" + } + } + } + } + } + } + }, + "/api/research/festivals": { + "get": { + "description": "List music festivals.", + "responses": { + "200": { + "description": "Festival list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchFestivalsResponse" + } + } + } + } + } + } + }, + "/api/research/genres": { + "get": { + "description": "List all available genre IDs and names. Use these IDs with the discover endpoint at GET /api/research/discover.", + "responses": { + "200": { + "description": "Genre list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchGenresResponse" + } + } + } + } + } + } + }, + "/api/research/insights": { + "get": { + "description": "Get AI-generated insights about an artist — automatically surfaced trends, milestones, and observations.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID (UUID).", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "AI-generated insights", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchInsightsResponse" + } + } + } + } + } + } + }, + "/api/research/instagram-posts": { + "get": { + "description": "Get an artist's top Instagram posts and reels, sorted by engagement.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID (UUID).", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Top Instagram posts and reels", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchInstagramPostsResponse" + } + } + } + } + } + } + }, + "/api/research/lookup": { + "get": { + "description": "Look up an artist by a platform URL or ID — Spotify URL, Spotify ID, Apple Music URL, etc.", + "parameters": [ + { + "name": "url", + "in": "query", + "required": true, + "description": "Platform URL or ID (e.g., Spotify artist URL, Spotify ID).", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Artist profile matching the platform URL", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchLookupResponse" + } + } + } + } + } + } + }, + "/api/research/metrics": { + "get": { + "description": "Get platform-specific metrics for an artist over time — followers, listeners, views, engagement. Supports 14 platforms.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID (UUID).", + "schema": { + "type": "string" + } + }, + { + "name": "source", + "in": "query", + "required": true, + "description": "Platform to get metrics for.", + "schema": { + "type": "string", + "enum": [ + "spotify", + "instagram", + "tiktok", + "twitter", + "facebook", + "youtube_channel", + "youtube_artist", + "soundcloud", + "deezer", + "twitch", + "line", + "melon", + "wikipedia", + "bandsintown" + ] + } + } + ], + "responses": { + "200": { + "description": "Platform metrics over time", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchMetricsResponse" + } + } + } + } + } + } + }, + "/api/research/milestones": { + "get": { + "description": "Get an artist's activity feed — playlist adds, chart entries, and other notable events. Each milestone includes a date, summary, platform, track name, and star rating.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Milestone list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchMilestonesResponse" + } + } + } + } + } + } + }, + "/api/research/people": { + "post": { + "description": "Search for people in the music industry — artists, managers, A&R reps, producers. Returns multi-source profiles including LinkedIn data.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchPeopleRequest" + } + } + } + }, + "responses": { + "200": { + "description": "People search results", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchPeopleResponse" + } + } + } + } + } + } + }, + "/api/research/playlist": { + "get": { + "description": "Get playlist metadata — name, description, follower count, track count, and curator info.", + "parameters": [ + { + "name": "platform", + "in": "query", + "required": true, + "schema": { + "type": "string", + "enum": [ + "spotify", + "applemusic", + "deezer", + "amazon", + "youtube" + ] + }, + "description": "Streaming platform." + }, + { + "name": "id", + "in": "query", + "required": true, + "description": "Playlist ID on the platform.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Playlist metadata", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchPlaylistResponse" + } + } + } + } + } + } + }, + "/api/research/playlists": { + "get": { + "description": "Get an artist's playlist placements — editorial, algorithmic, and indie playlists across platforms.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID (UUID).", + "schema": { + "type": "string" + } + }, + { + "name": "platform", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "spotify", + "applemusic", + "deezer", + "amazon", + "youtube" + ], + "default": "spotify" + } + }, + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "current", + "past" + ], + "default": "current" + } + }, + { + "name": "editorial", + "in": "query", + "required": false, + "description": "Only editorial playlists.", + "schema": { + "type": "boolean" + } + }, + { + "name": "since", + "in": "query", + "required": false, + "description": "Filter by date (YYYY-MM-DD).", + "schema": { + "type": "string", + "format": "date" + } + }, + { + "name": "sort", + "in": "query", + "required": false, + "description": "Sort results by this field.", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 20 + } + } + ], + "responses": { + "200": { + "description": "Playlist placements", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchPlaylistsResponse" + } + } + } + } + } + } + }, + "/api/research/profile": { + "get": { + "description": "Get a full artist profile — bio, genres, social URLs, label, career stage, and basic metrics.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID (UUID).", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Artist profile", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchProfileResponse" + } + } + } + } + } + } + }, + "/api/research/radio": { + "get": { + "description": "List radio stations tracked by Chartmetric. NOT artist-scoped. Returns station names, formats, and markets.", + "responses": { + "200": { + "description": "Radio station list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchRadioResponse" + } + } + } + } + } + } + }, + "/api/research/rank": { + "get": { + "description": "Get an artist's global Chartmetric ranking as a single integer value.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Artist rank", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchRankResponse" + } + } + } + } + } + } + }, + "/api/research/similar": { + "get": { + "description": "Find similar artists based on audience overlap, genre, mood, and musicality. Use for competitive analysis and collaboration discovery.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID (UUID).", + "schema": { + "type": "string" + } + }, + { + "name": "audience", + "in": "query", + "required": false, + "description": "Audience overlap weight.", + "schema": { + "type": "string", + "enum": [ + "high", + "medium", + "low" + ] + } + }, + { + "name": "genre", + "in": "query", + "required": false, + "description": "Genre similarity weight.", + "schema": { + "type": "string", + "enum": [ + "high", + "medium", + "low" + ] + } + }, + { + "name": "mood", + "in": "query", + "required": false, + "description": "Mood similarity weight.", + "schema": { + "type": "string", + "enum": [ + "high", + "medium", + "low" + ] + } + }, + { + "name": "musicality", + "in": "query", + "required": false, + "description": "Musicality similarity weight.", + "schema": { + "type": "string", + "enum": [ + "high", + "medium", + "low" + ] + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 10 + } + } + ], + "responses": { + "200": { + "description": "Similar artists with overlap scores", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchSimilarResponse" + } + } + } + } + } + } + }, + "/api/research/track": { + "get": { + "description": "Get track metadata — title, artist, album, release date, popularity, and platform IDs.", + "parameters": [ + { + "name": "q", + "in": "query", + "required": true, + "description": "Track name or Spotify URL.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Track metadata", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchTrackResponse" + } + } + } + } + } + } + }, + "/api/research/tracks": { + "get": { + "description": "Get all tracks by an artist with popularity data.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID (UUID).", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Artist tracks", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchTracksResponse" + } + } + } + } + } + } + }, + "/api/research/urls": { + "get": { + "description": "Get all social and streaming URLs for an artist — Spotify, Instagram, TikTok, YouTube, Twitter, SoundCloud, and more.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID (UUID).", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Social and streaming URLs", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchUrlsResponse" + } + } + } + } + } + } + }, + "/api/research/venues": { + "get": { + "description": "Get venues an artist has performed at, including capacity and location data.", + "parameters": [ + { + "name": "artist", + "in": "query", + "required": true, + "description": "Artist name or Recoup artist ID.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Venue list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchVenuesResponse" + } + } + } + } + } + } + }, + "/api/research/web": { + "post": { + "description": "Search the web for real-time information. Returns ranked results with titles, URLs, and content snippets. Use for narrative context, press coverage, and cultural research that structured data endpoints don't cover.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchWebRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Web search results", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResearchWebResponse" + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer" + }, + "apiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "x-api-key", + "description": "Your Recoup API key. [Learn more](/quickstart#api-keys)." + } + }, + "schemas": { + "ChatGenerateErrorResponse": { + "type": "object", + "required": [ + "status", + "message" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "message": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "ChatGenerateRequest": { + "type": "object", + "description": "Request body for chat generation. Exactly one of 'prompt' or 'messages' must be provided.", + "properties": { + "prompt": { + "type": "string", + "description": "Single text prompt for the assistant. Required if 'messages' is not provided." + }, + "messages": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UIMessage" + }, + "description": "Array of UIMessage objects for context. Required if 'prompt' is not provided." + }, + "artistId": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the artist (optional)" + }, + "model": { + "type": "string", + "description": "The AI model to use for text generation (optional)", + "example": "openai/gpt-5-mini" + }, + "excludeTools": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of tool names to exclude from execution", + "example": [ + "create_scheduled_actions" + ] + }, + "roomId": { + "type": "string", + "format": "uuid", + "description": "UUID of the chat room. If not provided, one will be generated automatically." + }, + "topic": { + "type": "string", + "description": "Topic name for the new chat room (e.g., 'Pulse Feb 2'). Only applies when creating a new room - ignored if room already exists. To edit the topic of an existing room, use [PATCH /api/chats](/api-reference/chat/update)." + } + } + }, + "ChatGenerateResponse": { + "type": "object", + "description": "Response from the chat generation endpoint", + "properties": { + "text": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentPart" + }, + "description": "Array of content parts from the AI model response" + }, + "reasoningText": { + "type": "string", + "nullable": true, + "description": "Optional reasoning or explanation for the response" + }, + "sources": { + "type": "array", + "items": { + "type": "object" + }, + "description": "Optional array of sources used for the response" + }, + "finishReason": { + "type": "string", + "description": "The reason why the generation finished", + "example": "stop" + }, + "usage": { + "$ref": "#/components/schemas/ChatGenerateUsage", + "description": "Token usage information" + }, + "response": { + "$ref": "#/components/schemas/ChatGenerateResponseMeta", + "description": "Additional response metadata" + } + } + }, + "ChatGenerateResponseMeta": { + "type": "object", + "description": "Additional response metadata", + "properties": { + "messages": { + "type": "array", + "items": { + "type": "object" + }, + "description": "Response messages" + }, + "headers": { + "type": "object", + "description": "Response headers" + }, + "body": { + "type": "object", + "description": "Response body" + } + } + }, + "ChatGenerateUsage": { + "type": "object", + "description": "Token usage information with detailed breakdown", + "properties": { + "inputTokens": { + "type": "integer", + "description": "Number of input tokens processed" + }, + "outputTokens": { + "type": "integer", + "description": "Number of output tokens generated" + }, + "totalTokens": { + "type": "integer", + "description": "Total tokens used (input + output)" + }, + "reasoningTokens": { + "type": "integer", + "description": "Number of reasoning tokens used" + }, + "cachedInputTokens": { + "type": "integer", + "description": "Number of cached input tokens" + } + } + }, + "ChatMessage": { + "type": "object", + "required": [ + "id", + "room_id", + "content", + "updated_at" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the memory message" + }, + "room_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the parent chat room" + }, + "content": { + "type": "object", + "description": "Structured message payload stored for the memory" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of the memory update" + } + } + }, + "ChatRoom": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the chat room" + }, + "account_id": { + "type": "string", + "format": "uuid", + "nullable": true, + "description": "UUID of the associated account (can be null if not set)" + }, + "topic": { + "type": "string", + "nullable": true, + "description": "Optional topic or description of the room (null if not provided)" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of the last update to the room" + }, + "artist_id": { + "type": "string", + "format": "uuid", + "nullable": true, + "description": "UUID of the associated artist account (null when not applicable)" + } + } + }, + "ChatStreamErrorResponse": { + "type": "object", + "required": [ + "status", + "message" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "message": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "ChatStreamRequest": { + "type": "object", + "description": "Request body for chat streaming. Exactly one of 'prompt' or 'messages' must be provided.", + "properties": { + "prompt": { + "type": "string", + "description": "Single text prompt for the assistant. Required if 'messages' is not provided." + }, + "messages": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UIMessage" + }, + "description": "Array of UIMessage objects for context. Required if 'prompt' is not provided." + }, + "artistId": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the artist (optional)" + }, + "model": { + "type": "string", + "description": "The AI model to use for text generation (optional)", + "example": "openai/gpt-5-mini" + }, + "excludeTools": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of tool names to exclude from execution", + "example": [ + "create_scheduled_actions" + ] + }, + "roomId": { + "type": "string", + "format": "uuid", + "description": "UUID of the chat room. If not provided, one will be generated automatically." + }, + "topic": { + "type": "string", + "description": "Topic name for the new chat room (e.g., 'Pulse Feb 2'). Only applies when creating a new room - ignored if room already exists. To edit the topic of an existing room, use [PATCH /api/chats](/api-reference/chat/update)." + } + } + }, + "CompactChatsRequest": { + "type": "object", + "required": [ + "chatId" + ], + "properties": { + "chatId": { + "type": "array", + "minItems": 1, + "items": { + "type": "string", + "format": "uuid" + }, + "description": "Array of chat IDs to compact" + }, + "prompt": { + "type": "string", + "description": "Optional prompt to control what information gets preserved in the compacted summary" + } + } + }, + "CompactChatsResponse": { + "type": "object", + "required": [ + "chats" + ], + "properties": { + "chats": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompactedChat" + }, + "description": "Array of compacted chat results" + } + } + }, + "CompactedChat": { + "type": "object", + "required": [ + "chatId", + "compacted" + ], + "properties": { + "chatId": { + "type": "string", + "format": "uuid", + "description": "The ID of the chat that was compacted" + }, + "compacted": { + "type": "string", + "description": "The compacted summary text of the chat" + } + } + }, + "ContentPart": { + "type": "object", + "description": "A part of the response content. See https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-text#content for details.", + "properties": { + "type": { + "type": "string", + "enum": [ + "text", + "tool-call", + "tool-result" + ], + "description": "The type of content part" + }, + "text": { + "type": "string", + "description": "The text content (present when type is 'text')" + } + } + }, + "CopyChatMessagesErrorResponse": { + "type": "object", + "required": [ + "status", + "error" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong." + } + } + }, + "CopyChatMessagesRequest": { + "type": "object", + "required": [ + "targetChatId" + ], + "properties": { + "targetChatId": { + "type": "string", + "format": "uuid", + "description": "Target chat room UUID to receive the copied messages." + }, + "clearExisting": { + "type": "boolean", + "default": true, + "description": "When true, existing messages in the target chat are deleted before copy." + } + } + }, + "CopyChatMessagesResponse": { + "type": "object", + "required": [ + "status", + "source_chat_id", + "target_chat_id", + "copied_count", + "cleared_existing" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "source_chat_id": { + "type": "string", + "format": "uuid", + "description": "Source chat room UUID." + }, + "target_chat_id": { + "type": "string", + "format": "uuid", + "description": "Target chat room UUID." + }, + "copied_count": { + "type": "integer", + "description": "Number of messages copied from source to target." + }, + "cleared_existing": { + "type": "boolean", + "description": "Whether existing target messages were deleted before copy." + } + } + }, + "CreateChatErrorResponse": { + "type": "object", + "required": [ + "status", + "message" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "message": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "CreateChatRequest": { + "type": "object", + "properties": { + "artistId": { + "type": "string", + "format": "uuid", + "description": "UUID of the artist account the chat is associated with" + }, + "chatId": { + "type": "string", + "format": "uuid", + "description": "UUID for the new chat (client-generated). If not provided, one will be generated automatically." + }, + "accountId": { + "type": "string", + "format": "uuid", + "description": "UUID of the account to create the chat for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, the chat is created for the API key's own account." + }, + "topic": { + "type": "string", + "description": "Topic name for the new chat room (e.g., 'Pulse Feb 2'). To edit the topic of an existing room, use [PATCH /api/chats](/api-reference/chat/update)." + } + } + }, + "CreateChatResponse": { + "type": "object", + "required": [ + "status", + "chat" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "chat": { + "$ref": "#/components/schemas/ChatRoom", + "description": "The created chat room object" + } + } + }, + "DeleteChatErrorResponse": { + "type": "object", + "required": [ + "status", + "error" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong." + } + } + }, + "DeleteChatRequest": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique identifier (UUID) of the chat room to delete." + } + } + }, + "DeleteChatResponse": { + "type": "object", + "required": [ + "status", + "id", + "message" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "The UUID of the deleted chat room." + }, + "message": { + "type": "string", + "description": "Success message describing the deletion result." + } + } + }, + "DeleteTrailingChatMessagesErrorResponse": { + "type": "object", + "required": [ + "status", + "error" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong." + }, + "missing_fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of missing or invalid parameter fields (when validation fails)." + } + } + }, + "DeleteTrailingChatMessagesResponse": { + "type": "object", + "required": [ + "status", + "chat_id", + "from_message_id" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "chat_id": { + "type": "string", + "format": "uuid", + "description": "The chat UUID where deletion was applied." + }, + "from_message_id": { + "type": "string", + "format": "uuid", + "description": "The message UUID used as the trailing deletion boundary." + } + } + }, + "Error": { + "required": [ + "error", + "message" + ], + "type": "object", + "properties": { + "error": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + }, + "GetChatArtistErrorResponse": { + "type": "object", + "required": [ + "status", + "error" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "GetChatArtistResponse": { + "type": "object", + "required": [ + "status", + "room_id", + "artist_id", + "artist_exists" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "room_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the chat room" + }, + "artist_id": { + "type": "string", + "format": "uuid", + "nullable": true, + "description": "UUID of the artist account associated with the chat, or null when no artist is linked" + }, + "artist_exists": { + "type": "boolean", + "description": "Whether an artist is linked to the chat room" + } + } + }, + "GetChatMessagesErrorResponse": { + "type": "object", + "required": [ + "status", + "error" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "GetChatMessagesResponse": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatMessage" + }, + "description": "Chronologically ordered list of messages for the chat" + } + } + }, + "GetChatSegmentErrorResponse": { + "type": "object", + "required": [ + "status", + "error" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "GetChatSegmentResponse": { + "type": "object", + "required": [ + "status", + "room_id", + "segment_id", + "segment_exists" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "room_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the chat room" + }, + "segment_id": { + "type": "string", + "format": "uuid", + "nullable": true, + "description": "UUID of the segment associated with the chat, or null when no segment is linked" + }, + "segment_exists": { + "type": "boolean", + "description": "Whether a segment is linked to the chat room" + } + } + }, + "GetChatsErrorResponse": { + "type": "object", + "required": [ + "status", + "error" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "GetChatsResponse": { + "type": "object", + "required": [ + "status", + "chats" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "chats": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatRoom" + }, + "description": "Array of chat room objects" + } + } + }, + "ResearchAlbum": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "release_date": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": true + }, + "ResearchAlbumsResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "albums": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResearchAlbum" + } + } + } + }, + "ResearchAudienceResponse": { + "type": "object", + "description": "Audience demographics breakdown — age ranges, gender split, and country distribution for the specified platform.", + "properties": { + "status": { + "type": "string" + }, + "age": { + "type": "array", + "description": "Age range breakdown", + "items": { + "type": "object", + "additionalProperties": true + } + }, + "gender": { + "type": "object", + "description": "Gender split percentages", + "additionalProperties": true + }, + "countries": { + "type": "array", + "description": "Top countries by audience share", + "items": { + "type": "object", + "additionalProperties": true + } + } + }, + "additionalProperties": true + }, + "ResearchCareerResponse": { + "type": "object", + "description": "Career timeline — milestones, trajectory, and career stage history.", + "properties": { + "status": { + "type": "string" + }, + "career_stage": { + "type": "string", + "description": "Current career stage (e.g., 'Mid-Level', 'Superstar')" + }, + "data": { + "type": "array", + "description": "Career timeline data points", + "items": { + "type": "object", + "additionalProperties": true + } + } + }, + "additionalProperties": true + }, + "ResearchChartsResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "data": { + "type": "object", + "description": "Chart data — structure varies by platform.", + "additionalProperties": true + } + } + }, + "ResearchCitiesEntry": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "City name." + }, + "country": { + "type": "string", + "description": "ISO country code." + }, + "listeners": { + "type": "integer", + "description": "Listener count in this city." + } + } + }, + "ResearchCitiesResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "cities": { + "type": "array", + "description": "Cities ranked by listener concentration.", + "items": { + "$ref": "#/components/schemas/ResearchCitiesEntry" + } + } + } + }, + "ResearchCuratorResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "name": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "image_url": { + "type": "string", + "format": "uri", + "nullable": true + }, + "num_playlists": { + "type": "integer", + "nullable": true + }, + "followers": { + "type": "integer", + "nullable": true + } + }, + "additionalProperties": true + }, + "ResearchDeepRequest": { + "type": "object", + "required": [ + "query" + ], + "description": "Request body for deep research. Performs comprehensive multi-source analysis.", + "properties": { + "query": { + "type": "string", + "description": "The research question — be specific and detailed for best results." + } + } + }, + "ResearchDeepResponse": { + "type": "object", + "description": "Comprehensive research report with citations.", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "content": { + "type": "string", + "description": "The full research report as markdown." + }, + "citations": { + "type": "array", + "description": "Source URLs cited in the report.", + "items": { + "type": "string", + "format": "uri" + } + } + } + }, + "ResearchDiscoverArtist": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "sp_monthly_listeners": { + "type": "integer", + "nullable": true + }, + "sp_followers": { + "type": "integer", + "nullable": true + }, + "tiktok_followers": { + "type": "integer", + "nullable": true + }, + "ins_followers": { + "type": "integer", + "nullable": true + }, + "country": { + "type": "string", + "nullable": true, + "description": "ISO country code." + } + }, + "additionalProperties": true + }, + "ResearchDiscoverResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "artists": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResearchDiscoverArtist" + } + } + } + }, + "ResearchEnrichRequest": { + "type": "object", + "required": [ + "input", + "schema" + ], + "properties": { + "input": { + "type": "string", + "description": "What to research (e.g., \"Drake rapper from Dallas Texas\")." + }, + "schema": { + "type": "object", + "description": "JSON schema defining the fields to extract.", + "additionalProperties": true + }, + "processor": { + "type": "string", + "enum": [ + "base", + "core", + "ultra" + ], + "default": "base", + "description": "Research depth: base (fast), core (balanced), ultra (comprehensive)." + } + } + }, + "ResearchEnrichResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "output": { + "type": "object", + "description": "Structured data matching the provided schema.", + "additionalProperties": true + }, + "research_basis": { + "type": "object", + "properties": { + "citations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri" + }, + "title": { + "type": "string" + }, + "field": { + "type": "string", + "description": "Which output field this citation supports." + } + } + } + } + } + } + } + }, + "ResearchExtractRequest": { + "type": "object", + "required": [ + "urls" + ], + "properties": { + "urls": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "maxItems": 10, + "description": "URLs to extract content from (max 10)." + }, + "objective": { + "type": "string", + "description": "What information to focus on (optional, max 3000 chars)." + }, + "full_content": { + "type": "boolean", + "default": false, + "description": "Return full page content instead of focused excerpts." + } + } + }, + "ResearchExtractResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResearchExtractResult" + } + }, + "errors": { + "type": "array", + "items": { + "type": "object" + }, + "description": "URLs that failed to extract." + } + } + }, + "ResearchExtractResult": { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri" + }, + "title": { + "type": "string", + "nullable": true + }, + "publish_date": { + "type": "string", + "nullable": true, + "description": "Publish date in YYYY-MM-DD format." + }, + "excerpts": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "description": "Focused excerpts as markdown." + }, + "full_content": { + "type": "string", + "nullable": true, + "description": "Full page content as markdown." + } + } + }, + "ResearchFestival": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "city": { + "type": "string", + "nullable": true + }, + "country": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": true + }, + "ResearchFestivalsResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "festivals": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResearchFestival" + } + } + } + }, + "ResearchGenre": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "id": { + "type": "integer" + } + } + }, + "ResearchGenresResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "genres": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResearchGenre" + } + } + } + }, + "ResearchInsight": { + "type": "object", + "properties": { + "text": { + "type": "string", + "description": "The insight text." + } + }, + "additionalProperties": true + }, + "ResearchInsightsResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "insights": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResearchInsight" + } + } + } + }, + "ResearchInstagramPostsResponse": { + "type": "object", + "description": "Top Instagram posts and reels sorted by engagement.", + "properties": { + "status": { + "type": "string" + }, + "posts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "likes": { + "type": "integer" + }, + "comments": { + "type": "integer" + }, + "timestamp": { + "type": "string" + } + }, + "additionalProperties": true + } + } + }, + "additionalProperties": true + }, + "ResearchLookupResponse": { + "type": "object", + "description": "Artist profile resolved from a platform URL or ID.", + "properties": { + "status": { + "type": "string" + }, + "id": { + "type": "integer", + "description": "Chartmetric artist ID" + }, + "spotify_id": { + "type": "string" + }, + "apple_music_id": { + "type": "string" + }, + "deezer_id": { + "type": "string" + } + }, + "additionalProperties": true + }, + "ResearchMetricsResponse": { + "type": "object", + "description": "Time-series metrics for a specific platform. Shape varies by source — typically an array of data points with timestamps and values (followers, listeners, views, etc.).", + "properties": { + "status": { + "type": "string" + }, + "data": { + "type": "array", + "description": "Array of time-series data points. Fields vary by platform.", + "items": { + "type": "object", + "additionalProperties": true + } + } + }, + "additionalProperties": true + }, + "ResearchMilestone": { + "type": "object", + "properties": { + "date": { + "type": "string", + "description": "Date of the milestone event." + }, + "summary": { + "type": "string", + "description": "Human-readable description of the event." + }, + "platform": { + "type": "string", + "description": "Platform where the event occurred (e.g. spotify, apple_music)." + }, + "track_name": { + "type": "string", + "description": "Name of the track involved, if any." + }, + "stars": { + "type": "integer", + "description": "Importance rating (1-5 stars)." + } + } + }, + "ResearchMilestonesResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "milestones": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResearchMilestone" + } + } + } + }, + "ResearchPeopleRequest": { + "type": "object", + "required": [ + "query" + ], + "properties": { + "query": { + "type": "string", + "description": "Natural language search for people (e.g., \"A&R reps at Atlantic Records\")." + }, + "num_results": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 10, + "description": "Number of results to return." + } + } + }, + "ResearchPeopleResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResearchPeopleResult" + } + } + } + }, + "ResearchPeopleResult": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "Person name and role." + }, + "url": { + "type": "string", + "format": "uri", + "description": "Profile URL (often LinkedIn)." + }, + "highlights": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Key excerpts from the profile." + }, + "summary": { + "type": "string", + "nullable": true, + "description": "Brief summary of the person." + } + } + }, + "ResearchPlaylistPlacement": { + "type": "object", + "properties": { + "playlist_name": { + "type": "string" + }, + "track_name": { + "type": "string" + }, + "position": { + "type": "integer", + "nullable": true + }, + "peak_position": { + "type": "integer", + "nullable": true + }, + "followers": { + "type": "integer", + "nullable": true, + "description": "Playlist follower count." + }, + "added_at": { + "type": "string", + "nullable": true, + "description": "When the track was added." + }, + "removed_at": { + "type": "string", + "nullable": true, + "description": "When the track was removed (past placements only)." + }, + "curator_name": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": true + }, + "ResearchPlaylistResponse": { + "type": "object", + "description": "Playlist metadata — name, description, follower count, track count, and curator info.", + "properties": { + "status": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "followers": { + "type": "integer" + }, + "num_tracks": { + "type": "integer" + }, + "curator_name": { + "type": "string" + } + }, + "additionalProperties": true + }, + "ResearchPlaylistsResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "placements": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResearchPlaylistPlacement" + } + } + } + }, + "ResearchProfileResponse": { + "type": "object", + "description": "Full artist profile — bio, genres, social links, label, images, and basic stats.", + "properties": { + "status": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "integer", + "description": "Chartmetric artist ID" + }, + "image_url": { + "type": "string" + }, + "genres": { + "type": "array", + "items": { + "type": "string" + } + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "type": "string" + }, + "hometown": { + "type": "string" + }, + "record_label": { + "type": "string" + }, + "sp_followers": { + "type": "integer" + }, + "sp_monthly_listeners": { + "type": "integer" + } + }, + "additionalProperties": true + }, + "ResearchRadioResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "stations": { + "type": "array", + "description": "Radio stations tracked by Chartmetric.", + "items": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "ResearchRankResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "rank": { + "type": "integer", + "nullable": true, + "description": "Global Chartmetric artist rank." + } + } + }, + "ResearchSearchResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "results": { + "type": "array", + "description": "Matching artists with IDs, names, and basic metadata.", + "items": { + "$ref": "#/components/schemas/ResearchSearchResult" + } + } + } + }, + "ResearchSearchResult": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "id": { + "type": "integer", + "description": "Internal ID for use with other research endpoints." + }, + "spotify_id": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": true + }, + "ResearchSimilarArtist": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "similarity": { + "type": "number", + "description": "Similarity score (0-1)." + }, + "career_stage": { + "type": "string", + "description": "undiscovered, developing, mid-level, mainstream, superstar, or legendary." + }, + "recent_momentum": { + "type": "string", + "description": "decline, gradual decline, steady, growth, or explosive growth." + }, + "sp_followers": { + "type": "integer", + "nullable": true + }, + "sp_monthly_listeners": { + "type": "integer", + "nullable": true + } + }, + "additionalProperties": true + }, + "ResearchSimilarResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "artists": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResearchSimilarArtist" + } + }, + "total": { + "type": "integer" + } + } + }, + "ResearchTrackItem": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "album_names": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "additionalProperties": true + }, + "ResearchTrackResponse": { + "type": "object", + "description": "Track metadata — title, artist, album, release date, popularity, and platform IDs.", + "properties": { + "status": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "integer", + "description": "Chartmetric track ID" + }, + "isrc": { + "type": "string" + }, + "album_name": { + "type": "string" + }, + "release_date": { + "type": "string" + }, + "artist_names": { + "type": "string" + } + }, + "additionalProperties": true + }, + "ResearchTracksResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "tracks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResearchTrackItem" + } + } + } + }, + "ResearchUrlEntry": { + "type": "object", + "properties": { + "domain": { + "type": "string", + "description": "Platform name (e.g., spotify, instagram)." + }, + "url": { + "type": "string", + "format": "uri" + } + } + }, + "ResearchUrlsResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "urls": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResearchUrlEntry" + } + } + } + }, + "ResearchVenue": { + "type": "object", + "properties": { + "venue_name": { + "type": "string", + "description": "Name of the venue." + }, + "venue_capacity": { + "type": "integer", + "nullable": true, + "description": "Venue capacity (seats or standing)." + }, + "city_name": { + "type": "string", + "description": "City where the venue is located." + }, + "country": { + "type": "string", + "description": "Two-letter country code." + }, + "events": { + "type": "array", + "description": "Events the artist performed at this venue.", + "items": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "ResearchVenuesResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "venues": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ResearchVenue" + } + } + } + }, + "ResearchWebRequest": { + "type": "object", + "required": [ + "query" + ], + "description": "Request body for web research.", + "properties": { + "query": { + "type": "string", + "description": "The search query — what you want to find on the web." + }, + "max_results": { + "type": "integer", + "minimum": 1, + "maximum": 20, + "default": 10, + "description": "Maximum number of results to return." + }, + "country": { + "type": "string", + "minLength": 2, + "maxLength": 2, + "description": "ISO country code for regional results (e.g., 'US', 'GB')." + } + } + }, + "ResearchWebResponse": { + "type": "object", + "description": "Web search results with titles, URLs, and content snippets.", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "results": { + "type": "array", + "description": "Ranked web search results.", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "url": { + "type": "string" + }, + "content": { + "type": "string" + } + } + } + }, + "formatted": { + "type": "string", + "description": "Results formatted as markdown for easy reading." + } + } + }, + "UIMessage": { + "type": "object", + "description": "A message in the chat conversation. See https://ai-sdk.dev/docs/reference/ai-sdk-core/ui-message for details.", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the message" + }, + "role": { + "type": "string", + "enum": [ + "user", + "assistant", + "system" + ], + "description": "The role of the message sender" + }, + "content": { + "type": "string", + "description": "The text content of the message" + } + } + }, + "UpdateChatErrorResponse": { + "type": "object", + "required": [ + "status", + "message" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "message": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "UpdateChatRequest": { + "type": "object", + "required": [ + "chatId", + "topic" + ], + "properties": { + "chatId": { + "type": "string", + "format": "uuid", + "description": "The unique identifier (UUID) of the chat room to update" + }, + "topic": { + "type": "string", + "minLength": 3, + "maxLength": 50, + "description": "The new display name for the chat room. Must be between 3 and 50 characters." + } + } + }, + "UpdateChatResponse": { + "type": "object", + "required": [ + "status", + "chat" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "chat": { + "$ref": "#/components/schemas/ChatRoom", + "description": "The updated chat room object" + } + } + } + } + } +} diff --git a/api-reference/openapi/social.json b/api-reference/openapi/social.json new file mode 100644 index 0000000..2a9e7c2 --- /dev/null +++ b/api-reference/openapi/social.json @@ -0,0 +1,2727 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Recoup API - Social", + "description": "API documentation for the Recoup platform - an AI agent platform for the music industry", + "license": { + "name": "MIT" + }, + "version": "1.0.0" + }, + "servers": [ + { + "url": "https://recoup-api.vercel.app" + } + ], + "paths": { + "/api/posts": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Retrieve all social media posts from an artist across all platforms. This endpoint aggregates posts from all connected social media profiles for the specified artist. Supports pagination for large post collections.", + "parameters": [ + { + "name": "artist_account_id", + "in": "query", + "description": "The unique identifier of the artist account to fetch posts for", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "page", + "in": "query", + "description": "The page number to retrieve (default: 1)", + "required": false, + "schema": { + "type": "integer", + "default": 1 + } + }, + { + "name": "limit", + "in": "query", + "description": "The number of records per page (default: 20, max: 100)", + "required": false, + "schema": { + "type": "integer", + "default": 20, + "maximum": 100 + } + } + ], + "responses": { + "200": { + "description": "Artist posts retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistPostsResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArtistPostsErrorResponse" + } + } + } + } + } + } + }, + "/api/comments": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Retrieve comments associated with an artist or a specific post, with support for pagination. This endpoint returns raw comment data including the comment text, associated post, and commenter's social profile reference.", + "parameters": [ + { + "name": "artist_account_id", + "in": "query", + "description": "The unique identifier of the artist account to fetch comments for", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "post_id", + "in": "query", + "description": "Filter comments by specific post", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "page", + "in": "query", + "description": "Page number for pagination (default: 1)", + "required": false, + "schema": { + "type": "integer", + "default": 1 + } + }, + { + "name": "limit", + "in": "query", + "description": "Number of comments per page (default: 10)", + "required": false, + "schema": { + "type": "integer", + "default": 10 + } + } + ], + "responses": { + "200": { + "description": "Comments retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CommentsResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CommentsErrorResponse" + } + } + } + } + } + } + }, + "/api/post/comments": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Retrieve comments for a specific social media post. This endpoint should be called after obtaining post IDs from the Social Posts endpoint. Returns detailed information about each commenter including their profile data, follower counts, and geographic region.", + "parameters": [ + { + "name": "post_id", + "in": "query", + "description": "The unique identifier of the post to fetch comments for", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "page", + "in": "query", + "description": "The page number to retrieve (default: 1)", + "required": false, + "schema": { + "type": "integer", + "default": 1 + } + }, + { + "name": "limit", + "in": "query", + "description": "The number of records per page (default: 20, max: 100)", + "required": false, + "schema": { + "type": "integer", + "default": 20, + "maximum": 100 + } + } + ], + "responses": { + "200": { + "description": "Post comments retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PostCommentsResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PostCommentsErrorResponse" + } + } + } + } + } + } + }, + "/api/spotify/search": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Search for artists, albums, tracks, and playlists using the Spotify API. This endpoint is a proxy to the official Spotify Search API.", + "parameters": [ + { + "name": "q", + "in": "query", + "description": "The search query keywords and optional field filters", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "type", + "in": "query", + "description": "A comma-separated list of item types to search across: album, artist, playlist, track, show, episode, audiobook", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "market", + "in": "query", + "description": "An ISO 3166-1 alpha-2 country code or 'from_token'", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return (default: 20, min: 1, max: 50)", + "required": false, + "schema": { + "type": "integer", + "default": 20, + "minimum": 1, + "maximum": 50 + } + }, + { + "name": "offset", + "in": "query", + "description": "The index of the first result to return (default: 0, max: 10000)", + "required": false, + "schema": { + "type": "integer", + "default": 0, + "maximum": 10000 + } + } + ], + "responses": { + "200": { + "description": "Search results retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpotifySearchResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpotifyErrorResponse" + } + } + } + } + } + } + }, + "/api/spotify/artist/": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Get Spotify catalog information for a single artist identified by their unique Spotify ID.", + "parameters": [ + { + "name": "id", + "in": "query", + "description": "The Spotify ID of the artist", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Artist retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpotifyGetArtistResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpotifyErrorResponse" + } + } + } + } + } + } + }, + "/api/spotify/artist/albums": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Get Spotify catalog information about an artist's albums.", + "parameters": [ + { + "name": "id", + "in": "query", + "description": "The Spotify ID of the artist", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "include_groups", + "in": "query", + "description": "A comma-separated list of keywords to filter the response. Valid values are: album, single, appears_on, compilation", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "market", + "in": "query", + "description": "An ISO 3166-1 alpha-2 country code. If specified, only content available in that market will be returned", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "The maximum number of items to return (default: 20, min: 1, max: 50)", + "required": false, + "schema": { + "type": "integer", + "default": 20, + "minimum": 1, + "maximum": 50 + } + }, + { + "name": "offset", + "in": "query", + "description": "The index of the first item to return (default: 0)", + "required": false, + "schema": { + "type": "integer", + "default": 0 + } + } + ], + "responses": { + "200": { + "description": "Artist albums retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpotifyArtistAlbumsResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpotifyErrorResponse" + } + } + } + } + } + } + }, + "/api/spotify/artist/topTracks": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Get an artist's top tracks by country.", + "parameters": [ + { + "name": "id", + "in": "query", + "description": "The Spotify ID of the artist", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "market", + "in": "query", + "description": "An ISO 3166-1 alpha-2 country code. If provided, only tracks available in that market are returned", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Artist top tracks retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpotifyArtistTopTracksResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpotifyErrorResponse" + } + } + } + } + } + } + }, + "/api/spotify/album": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Get Spotify catalog information for a single album.", + "parameters": [ + { + "name": "id", + "in": "query", + "description": "The Spotify ID of the album", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "market", + "in": "query", + "description": "An ISO 3166-1 alpha-2 country code. If provided, only content available in that market is returned", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Album retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpotifyAlbum" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SpotifyErrorResponse" + } + } + } + } + } + } + }, + "/api/instagram/comments": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Fetch Instagram comments for multiple post URLs using Apify's Instagram Comment Scraper. The actual comment data will be available in the Apify dataset after the run completes.", + "parameters": [ + { + "name": "postUrls", + "in": "query", + "description": "Array of Instagram post URLs to fetch comments for", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "style": "form", + "explode": true + }, + { + "name": "resultsLimit", + "in": "query", + "description": "Maximum number of comments to fetch (default: 10000)", + "required": false, + "schema": { + "type": "integer", + "default": 10000 + } + }, + { + "name": "isNewestComments", + "in": "query", + "description": "Whether to fetch newest comments first. Set to true for newest first, false for oldest first, or omit for platform default sorting", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Apify scraper run started successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApifyRunResult" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstagramErrorResponse" + } + } + } + } + } + } + }, + "/api/instagram/profiles": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Fetch Instagram profile information for multiple handles using Apify's Instagram Profile Scraper. The actual profile data will be available in the Apify dataset after the run completes.", + "parameters": [ + { + "name": "handles", + "in": "query", + "description": "Array of Instagram handles to fetch profiles for", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "style": "form", + "explode": true + } + ], + "responses": { + "200": { + "description": "Apify scraper run started successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApifyRunResult" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstagramErrorResponse" + } + } + } + } + } + } + }, + "/api/apify/scraper": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Check the status and retrieve results from Apify scraper runs. This endpoint uses the Apify API Client to fetch the current status of a scraper run and its results if available. Use the runId returned from endpoints like Instagram Comments, Instagram Profiles, Social Scrape, or Artist Socials Scrape to poll for results.", + "parameters": [ + { + "name": "runId", + "in": "query", + "description": "The ID of the Apify run to check status for. This is returned when starting a scrape via Instagram Comments, Instagram Profiles, Social Scrape, or Artist Socials Scrape endpoints.", + "required": true, + "schema": { + "type": "string" + }, + "example": "abc123xyz" + } + ], + "responses": { + "200": { + "description": "Scraper run status retrieved successfully. Returns status info for in-progress runs, or status info plus data for completed runs.", + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/ApifyScraperInProgressResponse" + }, + { + "$ref": "#/components/schemas/ApifyScraperCompletedResponse" + } + ] + } + } + } + }, + "400": { + "description": "Bad request - missing required runId parameter", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApifyScraperErrorResponse" + } + } + } + }, + "500": { + "description": "Server error - failed to fetch run status from Apify", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApifyScraperErrorResponse" + } + } + } + } + } + } + }, + "/api/x/search": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Search for tweets using the Twitter Search API, powered by agent-twitter-client (no Twitter API key required). Supports various search modes including Top, Latest, Photos, Videos, and Users.", + "parameters": [ + { + "name": "query", + "in": "query", + "description": "The search query. Any Twitter-compatible query format can be used (e.g., '#nodejs', 'from:username', etc.)", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "maxTweets", + "in": "query", + "description": "The maximum number of tweets to return", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "searchMode", + "in": "query", + "description": "The category filter to apply to the search", + "required": false, + "schema": { + "type": "string", + "enum": [ + "Top", + "Latest", + "Photos", + "Videos", + "Users" + ], + "default": "Latest" + } + } + ], + "responses": { + "200": { + "description": "Tweets retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TwitterSearchResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TwitterErrorResponse" + } + } + } + } + } + } + }, + "/api/x/trends": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Retrieve the current trending topics from Twitter using the getTrends method from agent-twitter-client (no Twitter API key required).", + "responses": { + "200": { + "description": "Trends retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TwitterTrendsResponse" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TwitterErrorResponse" + } + } + } + } + } + } + }, + "/api/social/scrape": { + "post": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Trigger a social profile scraping job for a given social_id. Use the Get Artist Socials endpoint first to retrieve the social_id values. The response returns Apify run metadata for polling status and retrieving results via the Apify Scraper Results API.", + "requestBody": { + "description": "Social profile to scrape", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SocialScrapeRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Scrape job triggered successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApifyRunResult" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SocialErrorResponse" + } + } + } + } + } + } + }, + "/api/social/posts": { + "get": { + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "description": "Retrieve all social media posts from a specific social profile. Call the Artist Socials endpoint first to obtain social IDs.", + "parameters": [ + { + "name": "social_id", + "in": "query", + "description": "The unique identifier (UUID) of the social profile to fetch posts for", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "latestFirst", + "in": "query", + "description": "Sort posts by most recent first (default: true)", + "required": false, + "schema": { + "type": "boolean", + "default": true + } + }, + { + "name": "page", + "in": "query", + "description": "The page number to retrieve (default: 1)", + "required": false, + "schema": { + "type": "integer", + "default": 1 + } + }, + { + "name": "limit", + "in": "query", + "description": "The number of records per page (default: 20, max: 100)", + "required": false, + "schema": { + "type": "integer", + "default": 20, + "maximum": 100 + } + } + ], + "responses": { + "200": { + "description": "Posts retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SocialPostsResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing required parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SocialErrorResponse" + } + } + } + } + } + } + }, + "/api/connectors": { + "get": { + "description": "List available connectors and their connection status. Returns all supported third-party integrations (e.g., Google Sheets, TikTok) along with whether they are currently connected.", + "parameters": [ + { + "name": "account_id", + "in": "query", + "description": "Optional account ID to get connectors for a different account (e.g., an artist, workspace, or organization). The authenticated account must have access to the specified account. Omit to get your own account's connectors.", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Connectors retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConnectorsResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid account_id format", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden - no access to the specified account", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "delete": { + "description": "Disconnect a connected account from a third-party service. This revokes the OAuth connection and removes stored credentials.", + "requestBody": { + "description": "Connection to disconnect", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DisconnectConnectorRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Connector disconnected successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DisconnectConnectorResponse" + } + } + } + }, + "400": { + "description": "Bad request - missing or invalid parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden - no access to the specified account or connection", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "post": { + "description": "Generate an OAuth authorization URL for connecting a third-party service. Redirect to the returned URL to complete the OAuth flow.", + "requestBody": { + "description": "Authorization request details", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthorizeConnectorRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Authorization URL generated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthorizeConnectorResponse" + } + } + } + }, + "400": { + "description": "Bad request - invalid connector or parameters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden - no access to the specified account", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer" + }, + "apiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "x-api-key", + "description": "Your Recoup API key. [Learn more](/quickstart#api-keys)." + } + }, + "schemas": { + "ApifyRunResult": { + "type": "object", + "properties": { + "runId": { + "type": "string", + "description": "Unique identifier for the Apify run" + }, + "datasetId": { + "type": "string", + "description": "Unique identifier for the dataset containing scraped data" + }, + "error": { + "type": "string", + "nullable": true, + "description": "Error message if the run failed (null if successful)" + } + } + }, + "ApifyScraperCompletedResponse": { + "type": "object", + "required": [ + "status", + "datasetId", + "data" + ], + "description": "Response when the Apify run has completed successfully", + "properties": { + "status": { + "type": "string", + "description": "Final status of the Apify run (typically 'SUCCEEDED')", + "example": "SUCCEEDED" + }, + "datasetId": { + "type": "string", + "description": "ID of the dataset containing the results", + "example": "def456uvw" + }, + "data": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + }, + "description": "Array of dataset items returned by the scraper. The structure of each item varies depending on the scraper type (Instagram Profile, Instagram Comments, etc.)", + "example": [ + { + "id": "123456789", + "username": "example_user", + "fullName": "Example User", + "biography": "This is a sample biography", + "followersCount": 1000, + "followsCount": 500, + "profilePicUrl": "https://example.com/profile.jpg" + } + ] + } + } + }, + "ApifyScraperErrorResponse": { + "type": "object", + "required": [ + "status", + "message" + ], + "description": "Error response from the Apify scraper results endpoint", + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status indicating an error occurred" + }, + "message": { + "type": "string", + "description": "Error message describing what went wrong", + "example": "runId is required" + } + } + }, + "ApifyScraperInProgressResponse": { + "type": "object", + "required": [ + "status", + "datasetId" + ], + "description": "Response when the Apify run is still in progress", + "properties": { + "status": { + "type": "string", + "description": "Current status of the Apify run (e.g., 'RUNNING', 'READY')", + "example": "RUNNING" + }, + "datasetId": { + "type": "string", + "description": "ID of the dataset that will contain the results when the run completes", + "example": "def456uvw" + } + } + }, + "ArtistPost": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the post" + }, + "post_url": { + "type": "string", + "description": "Direct URL to the post on the social platform" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of when the post was last updated" + } + } + }, + "ArtistPostsErrorResponse": { + "type": "object", + "required": [ + "status", + "error" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "ArtistPostsPagination": { + "type": "object", + "properties": { + "total_count": { + "type": "integer", + "description": "Total number of posts available" + }, + "page": { + "type": "integer", + "description": "Current page number" + }, + "limit": { + "type": "integer", + "description": "Number of posts per page" + }, + "total_pages": { + "type": "integer", + "description": "Total number of pages available" + } + } + }, + "ArtistPostsResponse": { + "type": "object", + "required": [ + "status", + "posts", + "pagination" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "posts": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ArtistPost" + }, + "description": "List of posts from the artist across all social platforms" + }, + "pagination": { + "$ref": "#/components/schemas/ArtistPostsPagination", + "description": "Pagination metadata for the response" + } + } + }, + "AuthorizeConnectorRequest": { + "type": "object", + "required": [ + "connector" + ], + "properties": { + "connector": { + "type": "string", + "description": "The connector slug to authorize (e.g., 'googlesheets', 'tiktok')" + }, + "callback_url": { + "type": "string", + "format": "uri", + "description": "Optional custom callback URL after OAuth completion" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "Optional account ID to connect a service for a different account (e.g., an artist, workspace, or organization). Use this when connecting an artist's TikTok or other service. The authenticated account must have access. Omit to connect for your own account." + } + } + }, + "AuthorizeConnectorResponse": { + "type": "object", + "required": [ + "success", + "data" + ], + "properties": { + "success": { + "type": "boolean" + }, + "data": { + "type": "object", + "required": [ + "connector", + "redirectUrl" + ], + "properties": { + "connector": { + "type": "string", + "description": "The connector slug being authorized" + }, + "redirectUrl": { + "type": "string", + "format": "uri", + "description": "URL to redirect to for OAuth authorization" + } + } + } + } + }, + "Comment": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the comment" + }, + "post_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the associated post" + }, + "social_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the social profile who made the comment" + }, + "comment": { + "type": "string", + "description": "Comment text content" + }, + "commented_at": { + "type": "string", + "format": "date-time", + "description": "Timestamp with timezone of when the comment was made" + } + } + }, + "CommentsErrorResponse": { + "type": "object", + "required": [ + "status", + "error" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "CommentsPagination": { + "type": "object", + "properties": { + "total_count": { + "type": "integer", + "description": "Total number of comments available" + }, + "page": { + "type": "integer", + "description": "Current page number" + }, + "limit": { + "type": "integer", + "description": "Number of comments per page" + }, + "total_pages": { + "type": "integer", + "description": "Total number of pages available" + } + } + }, + "CommentsResponse": { + "type": "object", + "required": [ + "status", + "comments", + "pagination" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "comments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Comment" + }, + "description": "List of comments for the specified artist or post" + }, + "pagination": { + "$ref": "#/components/schemas/CommentsPagination", + "description": "Pagination metadata for the response" + } + } + }, + "ConnectorInfo": { + "type": "object", + "required": [ + "slug", + "name", + "isConnected" + ], + "properties": { + "slug": { + "type": "string", + "description": "Unique identifier for the connector (e.g., 'googlesheets', 'tiktok')" + }, + "name": { + "type": "string", + "description": "Human-readable name of the connector" + }, + "isConnected": { + "type": "boolean", + "description": "Whether the connector is currently connected" + }, + "connectedAccountId": { + "type": "string", + "description": "The connected account ID (only present when isConnected is true)" + } + } + }, + "ConnectorsResponse": { + "type": "object", + "required": [ + "success", + "connectors" + ], + "properties": { + "success": { + "type": "boolean" + }, + "connectors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ConnectorInfo" + }, + "description": "List of available connectors with connection status" + } + } + }, + "DisconnectConnectorRequest": { + "type": "object", + "required": [ + "connected_account_id" + ], + "properties": { + "connected_account_id": { + "type": "string", + "description": "The connected account ID to disconnect (from ConnectorInfo.connectedAccountId)" + }, + "account_id": { + "type": "string", + "format": "uuid", + "description": "Optional account ID when disconnecting a connection that belongs to a different account (e.g., an artist). Required when the connection was created for another account rather than your own. The authenticated account must have access." + } + } + }, + "DisconnectConnectorResponse": { + "type": "object", + "required": [ + "success" + ], + "properties": { + "success": { + "type": "boolean" + }, + "message": { + "type": "string", + "description": "Status message" + } + } + }, + "Error": { + "required": [ + "error", + "message" + ], + "type": "object", + "properties": { + "error": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + }, + "InstagramErrorResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "message": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "PostComment": { + "type": "object", + "required": [ + "id", + "post_id", + "social_id", + "comment", + "commented_at", + "username", + "profile_url", + "post_url" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the comment record" + }, + "post_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the post this comment belongs to" + }, + "social_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the social profile that made the comment" + }, + "comment": { + "type": "string", + "description": "Text content of the comment" + }, + "commented_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of when the comment was posted" + }, + "username": { + "type": "string", + "description": "Username of the commenter" + }, + "avatar": { + "type": "string", + "nullable": true, + "description": "URL to the commenter's avatar image" + }, + "profile_url": { + "type": "string", + "description": "URL to the commenter's profile" + }, + "post_url": { + "type": "string", + "description": "URL to the post where the comment was made" + }, + "region": { + "type": "string", + "nullable": true, + "description": "Geographic region of the commenter" + }, + "bio": { + "type": "string", + "nullable": true, + "description": "Commenter's biography or description" + }, + "follower_count": { + "type": "integer", + "nullable": true, + "description": "Number of followers the commenter has" + }, + "following_count": { + "type": "integer", + "nullable": true, + "description": "Number of accounts the commenter follows" + } + } + }, + "PostCommentsErrorResponse": { + "type": "object", + "required": [ + "status", + "error" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Error message describing what went wrong" + } + } + }, + "PostCommentsPagination": { + "type": "object", + "properties": { + "total_count": { + "type": "integer", + "description": "Total number of comments available" + }, + "page": { + "type": "integer", + "description": "Current page number" + }, + "limit": { + "type": "integer", + "description": "Number of comments per page" + }, + "total_pages": { + "type": "integer", + "description": "Total number of pages available" + } + } + }, + "PostCommentsResponse": { + "type": "object", + "required": [ + "status", + "comments", + "pagination" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "comments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PostComment" + }, + "description": "List of comments for the specified post" + }, + "pagination": { + "$ref": "#/components/schemas/PostCommentsPagination", + "description": "Pagination metadata for the response" + } + } + }, + "SocialErrorResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "message": { + "type": "string", + "description": "Error message" + } + } + }, + "SocialPost": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the social's social_posts record" + }, + "post_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the social's posts record" + }, + "social_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the social's socials record" + }, + "post_url": { + "type": "string", + "description": "Direct URL to the post on the platform" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "ISO timestamp of when the post data was last updated" + } + } + }, + "SocialPostsPagination": { + "type": "object", + "properties": { + "total_count": { + "type": "integer", + "description": "Total number of posts available" + }, + "page": { + "type": "integer", + "description": "Current page number" + }, + "limit": { + "type": "integer", + "description": "Number of posts per page" + }, + "total_pages": { + "type": "integer", + "description": "Total number of pages available" + } + } + }, + "SocialPostsResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ], + "description": "Status of the request" + }, + "posts": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SocialPost" + }, + "description": "List of social media posts" + }, + "pagination": { + "$ref": "#/components/schemas/SocialPostsPagination" + } + } + }, + "SocialScrapeRequest": { + "type": "object", + "required": [ + "social_id" + ], + "properties": { + "social_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the social profile to scrape. Obtain this from the Get Artist Socials API." + } + } + }, + "SpotifyAlbum": { + "type": "object", + "properties": { + "album_type": { + "type": "string", + "enum": [ + "album", + "single", + "compilation" + ], + "description": "The type of the album" + }, + "total_tracks": { + "type": "integer", + "description": "The number of tracks in the album" + }, + "available_markets": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Markets in which the album is available" + }, + "external_urls": { + "$ref": "#/components/schemas/SpotifyExternalUrls" + }, + "href": { + "type": "string", + "description": "A link to the Web API endpoint providing full details" + }, + "id": { + "type": "string", + "description": "The Spotify ID for the album" + }, + "images": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpotifyImage" + }, + "description": "The cover art for the album in various sizes" + }, + "name": { + "type": "string", + "description": "The name of the album" + }, + "release_date": { + "type": "string", + "description": "The date the album was first released" + }, + "release_date_precision": { + "type": "string", + "enum": [ + "year", + "month", + "day" + ], + "description": "The precision with which release_date value is known" + }, + "restrictions": { + "type": "object", + "properties": { + "reason": { + "type": "string" + } + }, + "description": "Included when a content restriction is applied" + }, + "type": { + "type": "string", + "enum": [ + "album" + ], + "description": "The object type, always 'album'" + }, + "uri": { + "type": "string", + "description": "The Spotify URI for the album" + }, + "artists": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpotifySimplifiedArtist" + }, + "description": "The artists of the album" + }, + "tracks": { + "$ref": "#/components/schemas/SpotifyAlbumTracks", + "description": "The tracks of the album" + }, + "copyrights": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpotifyCopyright" + }, + "description": "Copyright statements of the album" + }, + "external_ids": { + "type": "object", + "properties": { + "isrc": { + "type": "string" + }, + "ean": { + "type": "string" + }, + "upc": { + "type": "string" + } + }, + "description": "Known external IDs for the album" + }, + "genres": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Deprecated. Always empty." + }, + "label": { + "type": "string", + "description": "The label associated with the album" + }, + "popularity": { + "type": "integer", + "description": "Popularity of the album (0-100)" + } + } + }, + "SpotifyAlbumTracks": { + "type": "object", + "properties": { + "href": { + "type": "string", + "description": "A link to the Web API endpoint" + }, + "limit": { + "type": "integer", + "description": "The maximum number of items in the response" + }, + "next": { + "type": "string", + "nullable": true, + "description": "URL to the next page of items" + }, + "offset": { + "type": "integer", + "description": "The offset of the items returned" + }, + "previous": { + "type": "string", + "nullable": true, + "description": "URL to the previous page" + }, + "total": { + "type": "integer", + "description": "Total number of items available" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpotifySimplifiedTrack" + }, + "description": "Array of simplified track objects" + } + } + }, + "SpotifyArtistAlbumsResponse": { + "type": "object", + "properties": { + "href": { + "type": "string", + "description": "A link to the Web API endpoint returning the full result" + }, + "limit": { + "type": "integer", + "description": "The maximum number of items in the response" + }, + "next": { + "type": "string", + "nullable": true, + "description": "URL to the next page of items" + }, + "offset": { + "type": "integer", + "description": "The offset of the items returned" + }, + "previous": { + "type": "string", + "nullable": true, + "description": "URL to the previous page of items" + }, + "total": { + "type": "integer", + "description": "The total number of items available" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpotifySimplifiedAlbum" + }, + "description": "Array of simplified album objects" + } + } + }, + "SpotifyArtistObject": { + "type": "object", + "properties": { + "external_urls": { + "$ref": "#/components/schemas/SpotifyExternalUrls" + }, + "followers": { + "$ref": "#/components/schemas/SpotifyFollowers" + }, + "genres": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of the genres the artist is associated with" + }, + "href": { + "type": "string", + "description": "A link to the Web API endpoint providing full details" + }, + "id": { + "type": "string", + "description": "The Spotify ID for the artist" + }, + "images": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpotifyImage" + }, + "description": "Images of the artist in various sizes" + }, + "name": { + "type": "string", + "description": "The name of the artist" + }, + "popularity": { + "type": "integer", + "description": "The popularity of the artist (0-100)" + }, + "type": { + "type": "string", + "enum": [ + "artist" + ], + "description": "The object type, always 'artist'" + }, + "uri": { + "type": "string", + "description": "The Spotify URI for the artist" + } + } + }, + "SpotifyArtistTopTracksResponse": { + "type": "object", + "properties": { + "tracks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpotifyTrack" + }, + "description": "Array of track objects" + } + } + }, + "SpotifyArtistsPaginated": { + "type": "object", + "properties": { + "href": { + "type": "string", + "description": "A link to the Web API endpoint returning the full result" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpotifyArtistObject" + }, + "description": "List of artist objects" + }, + "limit": { + "type": "integer", + "description": "The maximum number of items in the response" + }, + "next": { + "type": "string", + "nullable": true, + "description": "URL to the next page of items" + }, + "offset": { + "type": "integer", + "description": "The offset of the items returned" + }, + "previous": { + "type": "string", + "nullable": true, + "description": "URL to the previous page of items" + }, + "total": { + "type": "integer", + "description": "The total number of items available" + } + } + }, + "SpotifyCopyright": { + "type": "object", + "properties": { + "text": { + "type": "string", + "description": "The copyright text" + }, + "type": { + "type": "string", + "description": "The type of copyright" + } + } + }, + "SpotifyErrorResponse": { + "type": "object", + "properties": { + "error": { + "type": "object", + "properties": { + "status": { + "type": "integer", + "description": "HTTP status code" + }, + "message": { + "type": "string", + "description": "Error message" + } + }, + "description": "Error details" + } + } + }, + "SpotifyExternalUrls": { + "type": "object", + "properties": { + "spotify": { + "type": "string", + "description": "The Spotify URL for the object" + } + } + }, + "SpotifyFollowers": { + "type": "object", + "properties": { + "href": { + "type": "string", + "nullable": true, + "description": "This will always be set to null" + }, + "total": { + "type": "integer", + "description": "The total number of followers" + } + } + }, + "SpotifyGetArtistResponse": { + "type": "object", + "properties": { + "artist": { + "$ref": "#/components/schemas/SpotifyArtistObject", + "nullable": true, + "description": "The Spotify artist object (null if error)" + }, + "error": { + "type": "object", + "nullable": true, + "description": "Error object if request failed (null if successful)" + } + } + }, + "SpotifyImage": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "The source URL of the image" + }, + "height": { + "type": "integer", + "nullable": true, + "description": "The image height in pixels" + }, + "width": { + "type": "integer", + "nullable": true, + "description": "The image width in pixels" + } + } + }, + "SpotifySearchResponse": { + "type": "object", + "properties": { + "artists": { + "$ref": "#/components/schemas/SpotifyArtistsPaginated", + "description": "Search results for artists (if type includes artist)" + }, + "albums": { + "type": "object", + "description": "Search results for albums (if type includes album)" + }, + "tracks": { + "type": "object", + "description": "Search results for tracks (if type includes track)" + }, + "playlists": { + "type": "object", + "description": "Search results for playlists (if type includes playlist)" + } + } + }, + "SpotifySimplifiedAlbum": { + "type": "object", + "properties": { + "album_type": { + "type": "string", + "enum": [ + "album", + "single", + "compilation" + ], + "description": "The type of the album" + }, + "total_tracks": { + "type": "integer", + "description": "The number of tracks in the album" + }, + "available_markets": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Markets in which the album is available" + }, + "external_urls": { + "$ref": "#/components/schemas/SpotifyExternalUrls" + }, + "href": { + "type": "string", + "description": "A link to the Web API endpoint providing full details" + }, + "id": { + "type": "string", + "description": "The Spotify ID for the album" + }, + "images": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpotifyImage" + }, + "description": "The cover art for the album in various sizes" + }, + "name": { + "type": "string", + "description": "The name of the album" + }, + "release_date": { + "type": "string", + "description": "The date the album was first released" + }, + "release_date_precision": { + "type": "string", + "enum": [ + "year", + "month", + "day" + ], + "description": "The precision with which release_date value is known" + }, + "restrictions": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "description": "The reason for the restriction" + } + }, + "description": "Included when a content restriction is applied" + }, + "type": { + "type": "string", + "enum": [ + "album" + ], + "description": "The object type, always 'album'" + }, + "uri": { + "type": "string", + "description": "The Spotify URI for the album" + }, + "artists": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpotifySimplifiedArtist" + }, + "description": "The artists of the album" + }, + "album_group": { + "type": "string", + "enum": [ + "album", + "single", + "compilation", + "appears_on" + ], + "description": "The field to distinguish albums by various groups" + } + } + }, + "SpotifySimplifiedArtist": { + "type": "object", + "properties": { + "external_urls": { + "$ref": "#/components/schemas/SpotifyExternalUrls" + }, + "href": { + "type": "string", + "description": "A link to the Web API endpoint providing full details" + }, + "id": { + "type": "string", + "description": "The Spotify ID for the artist" + }, + "name": { + "type": "string", + "description": "The name of the artist" + }, + "type": { + "type": "string", + "enum": [ + "artist" + ], + "description": "The object type, always 'artist'" + }, + "uri": { + "type": "string", + "description": "The Spotify URI for the artist" + } + } + }, + "SpotifySimplifiedTrack": { + "type": "object", + "properties": { + "artists": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpotifySimplifiedArtist" + }, + "description": "The artists who performed the track" + }, + "available_markets": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Markets in which the track is available" + }, + "disc_number": { + "type": "integer", + "description": "Disc number the track is on" + }, + "duration_ms": { + "type": "integer", + "description": "Track length in milliseconds" + }, + "explicit": { + "type": "boolean", + "description": "Whether the track has explicit lyrics" + }, + "external_urls": { + "$ref": "#/components/schemas/SpotifyExternalUrls" + }, + "href": { + "type": "string", + "description": "Link to the Web API endpoint" + }, + "id": { + "type": "string", + "description": "Spotify ID for the track" + }, + "is_playable": { + "type": "boolean", + "description": "If true, the track is playable" + }, + "linked_from": { + "type": "object", + "description": "Track relinking info" + }, + "restrictions": { + "type": "object", + "properties": { + "reason": { + "type": "string" + } + } + }, + "name": { + "type": "string", + "description": "Track name" + }, + "preview_url": { + "type": "string", + "nullable": true, + "description": "URL to a 30 second preview" + }, + "track_number": { + "type": "integer", + "description": "Track number on the album" + }, + "type": { + "type": "string", + "enum": [ + "track" + ] + }, + "uri": { + "type": "string", + "description": "Spotify URI for the track" + }, + "is_local": { + "type": "boolean", + "description": "Whether from a local file" + } + } + }, + "SpotifyTrack": { + "type": "object", + "properties": { + "album": { + "$ref": "#/components/schemas/SpotifySimplifiedAlbum", + "description": "The album the track appears on" + }, + "artists": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SpotifySimplifiedArtist" + }, + "description": "Artists who performed the track" + }, + "available_markets": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Markets in which the track is available" + }, + "disc_number": { + "type": "integer", + "description": "Disc number the track is on" + }, + "duration_ms": { + "type": "integer", + "description": "Track length in milliseconds" + }, + "explicit": { + "type": "boolean", + "description": "Whether the track has explicit lyrics" + }, + "external_ids": { + "type": "object", + "properties": { + "isrc": { + "type": "string", + "description": "International Standard Recording Code" + }, + "ean": { + "type": "string", + "description": "International Article Number" + }, + "upc": { + "type": "string", + "description": "Universal Product Code" + } + }, + "description": "Known external IDs for the track" + }, + "external_urls": { + "$ref": "#/components/schemas/SpotifyExternalUrls" + }, + "href": { + "type": "string", + "description": "Link to the Web API endpoint with full details" + }, + "id": { + "type": "string", + "description": "Spotify ID for the track" + }, + "is_playable": { + "type": "boolean", + "description": "If true, the track is playable in the given market" + }, + "linked_from": { + "type": "object", + "description": "Information about the originally requested track when track relinking is applied" + }, + "restrictions": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "description": "The reason for the restriction" + } + }, + "description": "Content restriction information" + }, + "name": { + "type": "string", + "description": "Track name" + }, + "popularity": { + "type": "integer", + "description": "Popularity score (0-100)" + }, + "preview_url": { + "type": "string", + "nullable": true, + "description": "URL to a 30 second preview, if available" + }, + "track_number": { + "type": "integer", + "description": "Track number on the album" + }, + "type": { + "type": "string", + "enum": [ + "track" + ], + "description": "The object type, always 'track'" + }, + "uri": { + "type": "string", + "description": "The Spotify URI for the track" + }, + "is_local": { + "type": "boolean", + "description": "Whether the track is from a local file" + } + } + }, + "Tweet": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Tweet ID" + }, + "text": { + "type": "string", + "description": "Tweet text content" + }, + "username": { + "type": "string", + "description": "Username of the tweet author" + }, + "timestamp": { + "type": "integer", + "description": "Unix timestamp (ms) of when the tweet was posted" + }, + "createdAt": { + "type": "string", + "description": "ISO timestamp of when the tweet was posted" + }, + "isReply": { + "type": "boolean", + "description": "Whether the tweet is a reply" + }, + "isRetweet": { + "type": "boolean", + "description": "Whether the tweet is a retweet" + }, + "likes": { + "type": "integer", + "description": "Number of likes" + }, + "retweetCount": { + "type": "integer", + "description": "Number of retweets" + }, + "replies": { + "type": "integer", + "description": "Number of replies" + }, + "photos": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TwitterPhoto" + }, + "description": "Array of photo objects" + }, + "videos": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TwitterVideo" + }, + "description": "Array of video objects" + }, + "urls": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of URLs included in the tweet" + }, + "permanentUrl": { + "type": "string", + "description": "Permanent URL to the tweet" + }, + "quotedStatusId": { + "type": "string", + "description": "ID of the quoted tweet (if applicable)" + }, + "inReplyToStatusId": { + "type": "string", + "description": "ID of the tweet this is replying to (if applicable)" + }, + "hashtags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of hashtags in the tweet" + } + } + }, + "TwitterErrorResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "message": { + "type": "string", + "description": "Error message" + } + } + }, + "TwitterPhoto": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Photo ID" + }, + "url": { + "type": "string", + "description": "URL of the photo" + } + } + }, + "TwitterSearchResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "Status of the request", + "enum": [ + "success", + "error" + ] + }, + "tweets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Tweet" + }, + "description": "List of tweet objects" + } + } + }, + "TwitterTrendsResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "Status of the request", + "enum": [ + "success", + "error" + ] + }, + "trends": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of current trending topics on Twitter" + } + } + }, + "TwitterVideo": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Video ID" + }, + "preview": { + "type": "string", + "description": "URL of the video preview image" + }, + "url": { + "type": "string", + "description": "URL of the video" + } + } + } + } + } +} diff --git a/api-reference/organizations/add-artist.mdx b/api-reference/organizations/add-artist.mdx index ec3d671..d918efb 100644 --- a/api-reference/organizations/add-artist.mdx +++ b/api-reference/organizations/add-artist.mdx @@ -1,4 +1,4 @@ --- title: Add Artist to Organization -openapi: POST /api/organizations/artists +openapi: "/api-reference/openapi/accounts.json POST /api/organizations/artists" --- diff --git a/api-reference/organizations/create.mdx b/api-reference/organizations/create.mdx index 18677eb..55b34b5 100644 --- a/api-reference/organizations/create.mdx +++ b/api-reference/organizations/create.mdx @@ -1,4 +1,4 @@ --- title: Create Organization -openapi: POST /api/organizations +openapi: "/api-reference/openapi/accounts.json POST /api/organizations" --- diff --git a/api-reference/organizations/list.mdx b/api-reference/organizations/list.mdx index 2e6bb53..2731f60 100644 --- a/api-reference/organizations/list.mdx +++ b/api-reference/organizations/list.mdx @@ -1,4 +1,4 @@ --- title: Get Organizations -openapi: GET /api/organizations +openapi: "/api-reference/openapi/accounts.json GET /api/organizations" --- diff --git a/api-reference/post/comments.mdx b/api-reference/post/comments.mdx index 9c77d09..b4279c1 100644 --- a/api-reference/post/comments.mdx +++ b/api-reference/post/comments.mdx @@ -1,4 +1,4 @@ --- title: Get Post Comments -openapi: GET /api/post/comments +openapi: "/api-reference/openapi/social.json GET /api/post/comments" --- diff --git a/api-reference/posts/get.mdx b/api-reference/posts/get.mdx index 4bfee8e..def06ab 100644 --- a/api-reference/posts/get.mdx +++ b/api-reference/posts/get.mdx @@ -1,4 +1,4 @@ --- title: Get Artist Posts -openapi: GET /api/posts +openapi: "/api-reference/openapi/social.json GET /api/posts" --- diff --git a/api-reference/pulses/list.mdx b/api-reference/pulses/list.mdx index b08d254..2dfbf7d 100644 --- a/api-reference/pulses/list.mdx +++ b/api-reference/pulses/list.mdx @@ -1,4 +1,4 @@ --- title: 'List Pulses' -openapi: 'GET /api/pulses' +openapi: "/api-reference/openapi/accounts.json GET /api/pulses" --- diff --git a/api-reference/pulses/update.mdx b/api-reference/pulses/update.mdx index e909536..0cd35d7 100644 --- a/api-reference/pulses/update.mdx +++ b/api-reference/pulses/update.mdx @@ -1,4 +1,4 @@ --- title: 'Update Pulse' -openapi: 'PATCH /api/pulses' +openapi: "/api-reference/openapi/accounts.json PATCH /api/pulses" --- diff --git a/api-reference/research/albums.mdx b/api-reference/research/albums.mdx index ad026fd..923cc91 100644 --- a/api-reference/research/albums.mdx +++ b/api-reference/research/albums.mdx @@ -1,4 +1,4 @@ --- title: 'Albums' -openapi: 'GET /api/research/albums' +openapi: "/api-reference/openapi/research.json GET /api/research/albums" --- diff --git a/api-reference/research/audience.mdx b/api-reference/research/audience.mdx index 9a4b73f..d95cf3a 100644 --- a/api-reference/research/audience.mdx +++ b/api-reference/research/audience.mdx @@ -1,4 +1,4 @@ --- title: 'Audience Demographics' -openapi: 'GET /api/research/audience' +openapi: "/api-reference/openapi/research.json GET /api/research/audience" --- diff --git a/api-reference/research/career.mdx b/api-reference/research/career.mdx index 2544ff3..23fbf77 100644 --- a/api-reference/research/career.mdx +++ b/api-reference/research/career.mdx @@ -1,4 +1,4 @@ --- title: 'Career Timeline' -openapi: 'GET /api/research/career' +openapi: "/api-reference/openapi/research.json GET /api/research/career" --- diff --git a/api-reference/research/charts.mdx b/api-reference/research/charts.mdx index 25dead0..1c49044 100644 --- a/api-reference/research/charts.mdx +++ b/api-reference/research/charts.mdx @@ -1,4 +1,4 @@ --- title: 'Charts' -openapi: 'GET /api/research/charts' +openapi: "/api-reference/openapi/research.json GET /api/research/charts" --- diff --git a/api-reference/research/cities.mdx b/api-reference/research/cities.mdx index d379fa4..ff42539 100644 --- a/api-reference/research/cities.mdx +++ b/api-reference/research/cities.mdx @@ -1,4 +1,4 @@ --- title: 'Listener Cities' -openapi: 'GET /api/research/cities' +openapi: "/api-reference/openapi/research.json GET /api/research/cities" --- diff --git a/api-reference/research/curator.mdx b/api-reference/research/curator.mdx index 7761c0c..f9fd7a3 100644 --- a/api-reference/research/curator.mdx +++ b/api-reference/research/curator.mdx @@ -1,4 +1,4 @@ --- title: 'Curator' -openapi: 'GET /api/research/curator' +openapi: "/api-reference/openapi/research.json GET /api/research/curator" --- diff --git a/api-reference/research/deep.mdx b/api-reference/research/deep.mdx index 34bb0f3..51f433b 100644 --- a/api-reference/research/deep.mdx +++ b/api-reference/research/deep.mdx @@ -1,4 +1,4 @@ --- title: 'Deep Research' -openapi: 'POST /api/research/deep' +openapi: "/api-reference/openapi/research.json POST /api/research/deep" --- diff --git a/api-reference/research/discover.mdx b/api-reference/research/discover.mdx index c5c643e..60de0f9 100644 --- a/api-reference/research/discover.mdx +++ b/api-reference/research/discover.mdx @@ -1,4 +1,4 @@ --- title: 'Discover Artists' -openapi: 'GET /api/research/discover' +openapi: "/api-reference/openapi/research.json GET /api/research/discover" --- diff --git a/api-reference/research/enrich.mdx b/api-reference/research/enrich.mdx index 5d6a769..56d0acc 100644 --- a/api-reference/research/enrich.mdx +++ b/api-reference/research/enrich.mdx @@ -1,4 +1,4 @@ --- title: 'Enrich' -openapi: 'POST /api/research/enrich' +openapi: "/api-reference/openapi/research.json POST /api/research/enrich" --- diff --git a/api-reference/research/extract.mdx b/api-reference/research/extract.mdx index 40733c3..fe1ff79 100644 --- a/api-reference/research/extract.mdx +++ b/api-reference/research/extract.mdx @@ -1,4 +1,4 @@ --- title: 'Extract URL' -openapi: 'POST /api/research/extract' +openapi: "/api-reference/openapi/research.json POST /api/research/extract" --- diff --git a/api-reference/research/festivals.mdx b/api-reference/research/festivals.mdx index 97b3c0b..896d15c 100644 --- a/api-reference/research/festivals.mdx +++ b/api-reference/research/festivals.mdx @@ -1,4 +1,4 @@ --- title: 'Festivals' -openapi: 'GET /api/research/festivals' +openapi: "/api-reference/openapi/research.json GET /api/research/festivals" --- diff --git a/api-reference/research/genres.mdx b/api-reference/research/genres.mdx index 12b7795..050cefe 100644 --- a/api-reference/research/genres.mdx +++ b/api-reference/research/genres.mdx @@ -1,4 +1,4 @@ --- title: 'Genres' -openapi: 'GET /api/research/genres' +openapi: "/api-reference/openapi/research.json GET /api/research/genres" --- diff --git a/api-reference/research/insights.mdx b/api-reference/research/insights.mdx index 88695cf..2e2b5ca 100644 --- a/api-reference/research/insights.mdx +++ b/api-reference/research/insights.mdx @@ -1,4 +1,4 @@ --- title: 'AI Insights' -openapi: 'GET /api/research/insights' +openapi: "/api-reference/openapi/research.json GET /api/research/insights" --- diff --git a/api-reference/research/instagram-posts.mdx b/api-reference/research/instagram-posts.mdx index 9d598de..5ec8adb 100644 --- a/api-reference/research/instagram-posts.mdx +++ b/api-reference/research/instagram-posts.mdx @@ -1,4 +1,4 @@ --- title: 'Instagram Posts' -openapi: 'GET /api/research/instagram-posts' +openapi: "/api-reference/openapi/research.json GET /api/research/instagram-posts" --- diff --git a/api-reference/research/lookup.mdx b/api-reference/research/lookup.mdx index bda5bc2..485a9a6 100644 --- a/api-reference/research/lookup.mdx +++ b/api-reference/research/lookup.mdx @@ -1,4 +1,4 @@ --- title: 'Lookup by URL' -openapi: 'GET /api/research/lookup' +openapi: "/api-reference/openapi/research.json GET /api/research/lookup" --- diff --git a/api-reference/research/metrics.mdx b/api-reference/research/metrics.mdx index ff1b706..d042117 100644 --- a/api-reference/research/metrics.mdx +++ b/api-reference/research/metrics.mdx @@ -1,4 +1,4 @@ --- title: 'Platform Metrics' -openapi: 'GET /api/research/metrics' +openapi: "/api-reference/openapi/research.json GET /api/research/metrics" --- diff --git a/api-reference/research/milestones.mdx b/api-reference/research/milestones.mdx index c11f762..bfbc57e 100644 --- a/api-reference/research/milestones.mdx +++ b/api-reference/research/milestones.mdx @@ -1,4 +1,4 @@ --- title: 'Milestones' -openapi: 'GET /api/research/milestones' +openapi: "/api-reference/openapi/research.json GET /api/research/milestones" --- diff --git a/api-reference/research/people.mdx b/api-reference/research/people.mdx index 06b6d0a..6415e4c 100644 --- a/api-reference/research/people.mdx +++ b/api-reference/research/people.mdx @@ -1,4 +1,4 @@ --- title: 'People Search' -openapi: 'POST /api/research/people' +openapi: "/api-reference/openapi/research.json POST /api/research/people" --- diff --git a/api-reference/research/playlist.mdx b/api-reference/research/playlist.mdx index 0da706e..2b90c61 100644 --- a/api-reference/research/playlist.mdx +++ b/api-reference/research/playlist.mdx @@ -1,4 +1,4 @@ --- title: 'Playlist' -openapi: 'GET /api/research/playlist' +openapi: "/api-reference/openapi/research.json GET /api/research/playlist" --- diff --git a/api-reference/research/playlists.mdx b/api-reference/research/playlists.mdx index dce5080..3761378 100644 --- a/api-reference/research/playlists.mdx +++ b/api-reference/research/playlists.mdx @@ -1,4 +1,4 @@ --- title: 'Playlist Placements' -openapi: 'GET /api/research/playlists' +openapi: "/api-reference/openapi/research.json GET /api/research/playlists" --- diff --git a/api-reference/research/profile.mdx b/api-reference/research/profile.mdx index 1331b9a..cc03ae4 100644 --- a/api-reference/research/profile.mdx +++ b/api-reference/research/profile.mdx @@ -1,4 +1,4 @@ --- title: 'Artist Profile' -openapi: 'GET /api/research/profile' +openapi: "/api-reference/openapi/research.json GET /api/research/profile" --- diff --git a/api-reference/research/radio.mdx b/api-reference/research/radio.mdx index 6115267..feed417 100644 --- a/api-reference/research/radio.mdx +++ b/api-reference/research/radio.mdx @@ -1,4 +1,4 @@ --- title: 'Radio Stations' -openapi: 'GET /api/research/radio' +openapi: "/api-reference/openapi/research.json GET /api/research/radio" --- diff --git a/api-reference/research/rank.mdx b/api-reference/research/rank.mdx index a9fb36b..b08cbbe 100644 --- a/api-reference/research/rank.mdx +++ b/api-reference/research/rank.mdx @@ -1,4 +1,4 @@ --- title: 'Artist Rank' -openapi: 'GET /api/research/rank' +openapi: "/api-reference/openapi/research.json GET /api/research/rank" --- diff --git a/api-reference/research/search.mdx b/api-reference/research/search.mdx index ab64614..482602a 100644 --- a/api-reference/research/search.mdx +++ b/api-reference/research/search.mdx @@ -1,4 +1,4 @@ --- title: 'Search' -openapi: 'GET /api/research' +openapi: "/api-reference/openapi/research.json GET /api/research" --- diff --git a/api-reference/research/similar.mdx b/api-reference/research/similar.mdx index 623c4b8..bfbc922 100644 --- a/api-reference/research/similar.mdx +++ b/api-reference/research/similar.mdx @@ -1,4 +1,4 @@ --- title: 'Similar Artists' -openapi: 'GET /api/research/similar' +openapi: "/api-reference/openapi/research.json GET /api/research/similar" --- diff --git a/api-reference/research/track.mdx b/api-reference/research/track.mdx index cf1b522..160037d 100644 --- a/api-reference/research/track.mdx +++ b/api-reference/research/track.mdx @@ -1,4 +1,4 @@ --- title: 'Track' -openapi: 'GET /api/research/track' +openapi: "/api-reference/openapi/research.json GET /api/research/track" --- diff --git a/api-reference/research/tracks.mdx b/api-reference/research/tracks.mdx index 037ea66..58d0280 100644 --- a/api-reference/research/tracks.mdx +++ b/api-reference/research/tracks.mdx @@ -1,4 +1,4 @@ --- title: 'Tracks' -openapi: 'GET /api/research/tracks' +openapi: "/api-reference/openapi/research.json GET /api/research/tracks" --- diff --git a/api-reference/research/urls.mdx b/api-reference/research/urls.mdx index 54196e8..8e44770 100644 --- a/api-reference/research/urls.mdx +++ b/api-reference/research/urls.mdx @@ -1,4 +1,4 @@ --- title: 'Social URLs' -openapi: 'GET /api/research/urls' +openapi: "/api-reference/openapi/research.json GET /api/research/urls" --- diff --git a/api-reference/research/venues.mdx b/api-reference/research/venues.mdx index 06f0d22..00727b5 100644 --- a/api-reference/research/venues.mdx +++ b/api-reference/research/venues.mdx @@ -1,4 +1,4 @@ --- title: 'Venues' -openapi: 'GET /api/research/venues' +openapi: "/api-reference/openapi/research.json GET /api/research/venues" --- diff --git a/api-reference/research/web.mdx b/api-reference/research/web.mdx index 20373b6..cb3fbf2 100644 --- a/api-reference/research/web.mdx +++ b/api-reference/research/web.mdx @@ -1,4 +1,4 @@ --- title: 'Web Search' -openapi: 'POST /api/research/web' +openapi: "/api-reference/openapi/research.json POST /api/research/web" --- diff --git a/api-reference/sandboxes/create.mdx b/api-reference/sandboxes/create.mdx index b0a01e6..14212a6 100644 --- a/api-reference/sandboxes/create.mdx +++ b/api-reference/sandboxes/create.mdx @@ -1,4 +1,4 @@ --- title: 'Create Sandbox' -openapi: 'POST /api/sandboxes' +openapi: "/api-reference/openapi/content.json POST /api/sandboxes" --- diff --git a/api-reference/sandboxes/delete.mdx b/api-reference/sandboxes/delete.mdx index 075d05e..ceb938c 100644 --- a/api-reference/sandboxes/delete.mdx +++ b/api-reference/sandboxes/delete.mdx @@ -1,4 +1,4 @@ --- title: 'Delete Sandbox' -openapi: 'DELETE /api/sandboxes' +openapi: "/api-reference/openapi/content.json DELETE /api/sandboxes" --- diff --git a/api-reference/sandboxes/file.mdx b/api-reference/sandboxes/file.mdx index de8a7ee..0ae3374 100644 --- a/api-reference/sandboxes/file.mdx +++ b/api-reference/sandboxes/file.mdx @@ -1,4 +1,4 @@ --- title: 'Get File Contents' -openapi: 'GET /api/sandboxes/file' +openapi: "/api-reference/openapi/content.json GET /api/sandboxes/file" --- diff --git a/api-reference/sandboxes/list.mdx b/api-reference/sandboxes/list.mdx index 66a9cba..0423848 100644 --- a/api-reference/sandboxes/list.mdx +++ b/api-reference/sandboxes/list.mdx @@ -1,4 +1,4 @@ --- title: 'List Sandboxes' -openapi: 'GET /api/sandboxes' +openapi: "/api-reference/openapi/content.json GET /api/sandboxes" --- diff --git a/api-reference/sandboxes/setup.mdx b/api-reference/sandboxes/setup.mdx index 4922c80..ebe5657 100644 --- a/api-reference/sandboxes/setup.mdx +++ b/api-reference/sandboxes/setup.mdx @@ -1,4 +1,4 @@ --- title: 'Setup Sandbox' -openapi: 'POST /api/sandboxes/setup' +openapi: "/api-reference/openapi/content.json POST /api/sandboxes/setup" --- diff --git a/api-reference/sandboxes/snapshot.mdx b/api-reference/sandboxes/snapshot.mdx index 97f9a87..2465f27 100644 --- a/api-reference/sandboxes/snapshot.mdx +++ b/api-reference/sandboxes/snapshot.mdx @@ -1,4 +1,4 @@ --- title: 'Update Snapshot' -openapi: 'PATCH /api/sandboxes' +openapi: "/api-reference/openapi/content.json PATCH /api/sandboxes" --- diff --git a/api-reference/sandboxes/upload.mdx b/api-reference/sandboxes/upload.mdx index bc6990a..e176f66 100644 --- a/api-reference/sandboxes/upload.mdx +++ b/api-reference/sandboxes/upload.mdx @@ -1,4 +1,4 @@ --- title: 'Upload Files' -openapi: 'POST /api/sandboxes/files' +openapi: "/api-reference/openapi/content.json POST /api/sandboxes/files" --- diff --git a/api-reference/segment/fans.mdx b/api-reference/segment/fans.mdx index 55cc9c5..d0bca41 100644 --- a/api-reference/segment/fans.mdx +++ b/api-reference/segment/fans.mdx @@ -1,4 +1,4 @@ --- title: Get Segment Fans -openapi: GET /api/segment/fans +openapi: "/api-reference/openapi/releases.json GET /api/segment/fans" --- diff --git a/api-reference/social/posts.mdx b/api-reference/social/posts.mdx index b73e743..7440aa8 100644 --- a/api-reference/social/posts.mdx +++ b/api-reference/social/posts.mdx @@ -1,4 +1,4 @@ --- title: 'Get Social Posts' -openapi: 'GET /api/social/posts' +openapi: "/api-reference/openapi/social.json GET /api/social/posts" --- diff --git a/api-reference/social/scrape.mdx b/api-reference/social/scrape.mdx index a2236c2..f5d4d18 100644 --- a/api-reference/social/scrape.mdx +++ b/api-reference/social/scrape.mdx @@ -1,4 +1,4 @@ --- title: 'Social Scrape' -openapi: 'POST /api/social/scrape' +openapi: "/api-reference/openapi/social.json POST /api/social/scrape" --- diff --git a/api-reference/songs/analyze-presets.mdx b/api-reference/songs/analyze-presets.mdx index fd24fb2..4acd628 100644 --- a/api-reference/songs/analyze-presets.mdx +++ b/api-reference/songs/analyze-presets.mdx @@ -1,4 +1,4 @@ --- title: 'List Analyze Presets' -openapi: 'GET /api/songs/analyze/presets' +openapi: "/api-reference/openapi/releases.json GET /api/songs/analyze/presets" --- diff --git a/api-reference/songs/analyze.mdx b/api-reference/songs/analyze.mdx index 2905518..a3458b0 100644 --- a/api-reference/songs/analyze.mdx +++ b/api-reference/songs/analyze.mdx @@ -1,4 +1,4 @@ --- title: 'Analyze Songs' -openapi: 'POST /api/songs/analyze' +openapi: "/api-reference/openapi/releases.json POST /api/songs/analyze" --- diff --git a/api-reference/spotify/album.mdx b/api-reference/spotify/album.mdx index a3be57d..b4eae1d 100644 --- a/api-reference/spotify/album.mdx +++ b/api-reference/spotify/album.mdx @@ -1,4 +1,4 @@ --- title: 'Get Album' -openapi: 'GET /api/spotify/album' +openapi: "/api-reference/openapi/social.json GET /api/spotify/album" --- diff --git a/api-reference/spotify/artist-albums.mdx b/api-reference/spotify/artist-albums.mdx index 9dcfb8d..e3dd220 100644 --- a/api-reference/spotify/artist-albums.mdx +++ b/api-reference/spotify/artist-albums.mdx @@ -1,4 +1,4 @@ --- title: 'Get Artist Albums' -openapi: 'GET /api/spotify/artist/albums' +openapi: "/api-reference/openapi/social.json GET /api/spotify/artist/albums" --- diff --git a/api-reference/spotify/artist-top-tracks.mdx b/api-reference/spotify/artist-top-tracks.mdx index 426b7af..b5ee0e5 100644 --- a/api-reference/spotify/artist-top-tracks.mdx +++ b/api-reference/spotify/artist-top-tracks.mdx @@ -1,4 +1,4 @@ --- title: 'Get Artist Top Tracks' -openapi: 'GET /api/spotify/artist/topTracks' +openapi: "/api-reference/openapi/social.json GET /api/spotify/artist/topTracks" --- diff --git a/api-reference/spotify/artist.mdx b/api-reference/spotify/artist.mdx index de4204c..2e4397b 100644 --- a/api-reference/spotify/artist.mdx +++ b/api-reference/spotify/artist.mdx @@ -1,4 +1,4 @@ --- title: 'Get Artist' -openapi: 'GET /api/spotify/artist/' +openapi: "/api-reference/openapi/social.json GET /api/spotify/artist/" --- diff --git a/api-reference/spotify/search.mdx b/api-reference/spotify/search.mdx index aea2441..f49c546 100644 --- a/api-reference/spotify/search.mdx +++ b/api-reference/spotify/search.mdx @@ -1,4 +1,4 @@ --- title: 'Search' -openapi: 'GET /api/spotify/search' +openapi: "/api-reference/openapi/social.json GET /api/spotify/search" --- diff --git a/api-reference/subscriptions/get.mdx b/api-reference/subscriptions/get.mdx index d513375..8a36d82 100644 --- a/api-reference/subscriptions/get.mdx +++ b/api-reference/subscriptions/get.mdx @@ -1,4 +1,4 @@ --- title: 'Get Subscriptions' -openapi: 'GET /api/subscriptions' +openapi: "/api-reference/openapi/accounts.json GET /api/subscriptions" --- diff --git a/api-reference/tasks/create.mdx b/api-reference/tasks/create.mdx index 99a6e51..b0efa95 100644 --- a/api-reference/tasks/create.mdx +++ b/api-reference/tasks/create.mdx @@ -1,4 +1,4 @@ --- title: 'Create Task' -openapi: 'POST /api/tasks' +openapi: "/api-reference/openapi/releases.json POST /api/tasks" --- diff --git a/api-reference/tasks/delete.mdx b/api-reference/tasks/delete.mdx index 7a34680..6358324 100644 --- a/api-reference/tasks/delete.mdx +++ b/api-reference/tasks/delete.mdx @@ -1,4 +1,4 @@ --- title: 'Delete Task' -openapi: 'DELETE /api/tasks' +openapi: "/api-reference/openapi/releases.json DELETE /api/tasks" --- diff --git a/api-reference/tasks/get.mdx b/api-reference/tasks/get.mdx index facff38..c2f10a8 100644 --- a/api-reference/tasks/get.mdx +++ b/api-reference/tasks/get.mdx @@ -1,4 +1,4 @@ --- title: 'Get Tasks' -openapi: 'GET /api/tasks' +openapi: "/api-reference/openapi/releases.json GET /api/tasks" --- diff --git a/api-reference/tasks/runs.mdx b/api-reference/tasks/runs.mdx index 6b5b120..6954bf5 100644 --- a/api-reference/tasks/runs.mdx +++ b/api-reference/tasks/runs.mdx @@ -1,4 +1,4 @@ --- title: 'Get Task Runs' -openapi: 'GET /api/tasks/runs' +openapi: "/api-reference/openapi/releases.json GET /api/tasks/runs" --- diff --git a/api-reference/tasks/update.mdx b/api-reference/tasks/update.mdx index a6b1a01..5934c48 100644 --- a/api-reference/tasks/update.mdx +++ b/api-reference/tasks/update.mdx @@ -1,4 +1,4 @@ --- title: 'Update Task' -openapi: 'PATCH /api/tasks' +openapi: "/api-reference/openapi/releases.json PATCH /api/tasks" --- diff --git a/api-reference/transcribe/audio.mdx b/api-reference/transcribe/audio.mdx index 88fd6a0..30861ee 100644 --- a/api-reference/transcribe/audio.mdx +++ b/api-reference/transcribe/audio.mdx @@ -1,4 +1,4 @@ --- title: 'Transcribe Audio' -openapi: 'POST /api/transcribe' +openapi: "/api-reference/openapi/content.json POST /api/transcribe" --- diff --git a/api-reference/workspaces/create.mdx b/api-reference/workspaces/create.mdx index 1c12f63..258ba86 100644 --- a/api-reference/workspaces/create.mdx +++ b/api-reference/workspaces/create.mdx @@ -1,4 +1,4 @@ --- title: Create Workspace -openapi: POST /api/workspaces +openapi: "/api-reference/openapi/accounts.json POST /api/workspaces" --- diff --git a/api-reference/x/search.mdx b/api-reference/x/search.mdx index f361d8c..f7478bf 100644 --- a/api-reference/x/search.mdx +++ b/api-reference/x/search.mdx @@ -1,4 +1,4 @@ --- title: 'Search Tweets' -openapi: 'GET /api/x/search' +openapi: "/api-reference/openapi/social.json GET /api/x/search" --- diff --git a/api-reference/x/trends.mdx b/api-reference/x/trends.mdx index 07497b7..465a456 100644 --- a/api-reference/x/trends.mdx +++ b/api-reference/x/trends.mdx @@ -1,4 +1,4 @@ --- title: 'Get Trends' -openapi: 'GET /api/x/trends' +openapi: "/api-reference/openapi/social.json GET /api/x/trends" ---