diff --git a/api-reference/openapi.json b/api-reference/openapi.json
index 8fea02f..2f09832 100644
--- a/api-reference/openapi.json
+++ b/api-reference/openapi.json
@@ -2369,7 +2369,7 @@
},
"/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.",
+ "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 \u2014 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,
@@ -4240,14 +4240,23 @@
"required": false,
"schema": {
"type": "string",
- "enum": ["all", "daily", "weekly", "monthly"],
+ "enum": [
+ "all",
+ "daily",
+ "weekly",
+ "monthly"
+ ],
"default": "all"
}
}
],
"security": [
- { "apiKeyAuth": [] },
- { "bearerAuth": [] }
+ {
+ "apiKeyAuth": []
+ },
+ {
+ "bearerAuth": []
+ }
],
"responses": {
"200": {
@@ -4256,11 +4265,19 @@
"application/json": {
"schema": {
"type": "object",
- "required": ["status", "total", "total_pull_requests", "tags_with_pull_requests", "tags"],
+ "required": [
+ "status",
+ "total",
+ "total_pull_requests",
+ "tags_with_pull_requests",
+ "tags"
+ ],
"properties": {
"status": {
"type": "string",
- "enum": ["success"],
+ "enum": [
+ "success"
+ ],
"description": "Status of the request"
},
"total": {
@@ -4283,7 +4300,14 @@
"description": "List of Slack tag events",
"items": {
"type": "object",
- "required": ["user_id", "user_name", "prompt", "timestamp", "channel_id", "channel_name"],
+ "required": [
+ "user_id",
+ "user_name",
+ "prompt",
+ "timestamp",
+ "channel_id",
+ "channel_name"
+ ],
"properties": {
"user_id": {
"type": "string",
@@ -4296,7 +4320,10 @@
"example": "Jane Smith"
},
"user_avatar": {
- "type": ["string", "null"],
+ "type": [
+ "string",
+ "null"
+ ],
"description": "URL of the Slack avatar",
"example": "https://avatars.slack-edge.com/..."
},
@@ -4329,7 +4356,9 @@
"format": "uri",
"example": "https://github.com/recoupable/api/pull/42"
},
- "example": ["https://github.com/recoupable/api/pull/42"]
+ "example": [
+ "https://github.com/recoupable/api/pull/42"
+ ]
}
}
}
@@ -4343,7 +4372,9 @@
"description": "Unauthorized - missing or invalid credentials",
"content": {
"application/json": {
- "schema": { "$ref": "#/components/schemas/AccountErrorResponse" }
+ "schema": {
+ "$ref": "#/components/schemas/AccountErrorResponse"
+ }
}
}
},
@@ -4351,7 +4382,9 @@
"description": "Forbidden - authenticated account is not a Recoup admin",
"content": {
"application/json": {
- "schema": { "$ref": "#/components/schemas/AccountErrorResponse" }
+ "schema": {
+ "$ref": "#/components/schemas/AccountErrorResponse"
+ }
}
}
},
@@ -4359,7 +4392,9 @@
"description": "Internal server error",
"content": {
"application/json": {
- "schema": { "$ref": "#/components/schemas/AccountErrorResponse" }
+ "schema": {
+ "$ref": "#/components/schemas/AccountErrorResponse"
+ }
}
}
}
@@ -4377,14 +4412,23 @@
"required": false,
"schema": {
"type": "string",
- "enum": ["all", "daily", "weekly", "monthly"],
+ "enum": [
+ "all",
+ "daily",
+ "weekly",
+ "monthly"
+ ],
"default": "all"
}
}
],
"security": [
- { "apiKeyAuth": [] },
- { "bearerAuth": [] }
+ {
+ "apiKeyAuth": []
+ },
+ {
+ "bearerAuth": []
+ }
],
"responses": {
"200": {
@@ -4393,11 +4437,19 @@
"application/json": {
"schema": {
"type": "object",
- "required": ["status", "total", "total_videos", "tags_with_videos", "tags"],
+ "required": [
+ "status",
+ "total",
+ "total_videos",
+ "tags_with_videos",
+ "tags"
+ ],
"properties": {
"status": {
"type": "string",
- "enum": ["success"],
+ "enum": [
+ "success"
+ ],
"description": "Status of the request"
},
"total": {
@@ -4420,7 +4472,14 @@
"description": "List of Slack tag events",
"items": {
"type": "object",
- "required": ["user_id", "user_name", "prompt", "timestamp", "channel_id", "channel_name"],
+ "required": [
+ "user_id",
+ "user_name",
+ "prompt",
+ "timestamp",
+ "channel_id",
+ "channel_name"
+ ],
"properties": {
"user_id": {
"type": "string",
@@ -4433,7 +4492,10 @@
"example": "Jane Smith"
},
"user_avatar": {
- "type": ["string", "null"],
+ "type": [
+ "string",
+ "null"
+ ],
"description": "URL of the Slack avatar",
"example": "https://avatars.slack-edge.com/..."
},
@@ -4466,7 +4528,9 @@
"format": "uri",
"example": "https://recoupable.com/v/abc123"
},
- "example": ["https://recoupable.com/v/abc123"]
+ "example": [
+ "https://recoupable.com/v/abc123"
+ ]
}
}
}
@@ -4480,7 +4544,9 @@
"description": "Unauthorized - missing or invalid credentials",
"content": {
"application/json": {
- "schema": { "$ref": "#/components/schemas/AccountErrorResponse" }
+ "schema": {
+ "$ref": "#/components/schemas/AccountErrorResponse"
+ }
}
}
},
@@ -4488,7 +4554,9 @@
"description": "Forbidden - authenticated account is not a Recoup admin",
"content": {
"application/json": {
- "schema": { "$ref": "#/components/schemas/AccountErrorResponse" }
+ "schema": {
+ "$ref": "#/components/schemas/AccountErrorResponse"
+ }
}
}
},
@@ -4496,7 +4564,9 @@
"description": "Internal server error",
"content": {
"application/json": {
- "schema": { "$ref": "#/components/schemas/AccountErrorResponse" }
+ "schema": {
+ "$ref": "#/components/schemas/AccountErrorResponse"
+ }
}
}
}
@@ -4526,8 +4596,12 @@
}
],
"security": [
- { "apiKeyAuth": [] },
- { "bearerAuth": [] }
+ {
+ "apiKeyAuth": []
+ },
+ {
+ "bearerAuth": []
+ }
],
"responses": {
"200": {
@@ -4536,11 +4610,16 @@
"application/json": {
"schema": {
"type": "object",
- "required": ["status", "pull_requests"],
+ "required": [
+ "status",
+ "pull_requests"
+ ],
"properties": {
"status": {
"type": "string",
- "enum": ["success"],
+ "enum": [
+ "success"
+ ],
"description": "Status of the request"
},
"pull_requests": {
@@ -4548,7 +4627,10 @@
"description": "Status for each provided pull request URL",
"items": {
"type": "object",
- "required": ["url", "status"],
+ "required": [
+ "url",
+ "status"
+ ],
"properties": {
"url": {
"type": "string",
@@ -4558,7 +4640,11 @@
},
"status": {
"type": "string",
- "enum": ["open", "closed", "merged"],
+ "enum": [
+ "open",
+ "closed",
+ "merged"
+ ],
"description": "The current status of the pull request",
"example": "merged"
}
@@ -4574,7 +4660,9 @@
"description": "Bad request - missing or invalid pull_requests parameter",
"content": {
"application/json": {
- "schema": { "$ref": "#/components/schemas/AccountErrorResponse" }
+ "schema": {
+ "$ref": "#/components/schemas/AccountErrorResponse"
+ }
}
}
},
@@ -4582,7 +4670,9 @@
"description": "Unauthorized - missing or invalid credentials",
"content": {
"application/json": {
- "schema": { "$ref": "#/components/schemas/AccountErrorResponse" }
+ "schema": {
+ "$ref": "#/components/schemas/AccountErrorResponse"
+ }
}
}
},
@@ -4590,7 +4680,9 @@
"description": "Forbidden - authenticated account is not a Recoup admin",
"content": {
"application/json": {
- "schema": { "$ref": "#/components/schemas/AccountErrorResponse" }
+ "schema": {
+ "$ref": "#/components/schemas/AccountErrorResponse"
+ }
}
}
},
@@ -4598,7 +4690,9 @@
"description": "Internal server error",
"content": {
"application/json": {
- "schema": { "$ref": "#/components/schemas/AccountErrorResponse" }
+ "schema": {
+ "$ref": "#/components/schemas/AccountErrorResponse"
+ }
}
}
}
@@ -4727,7 +4821,9 @@
"required": true,
"schema": {
"type": "string",
- "enum": ["slack"]
+ "enum": [
+ "slack"
+ ]
}
}
],
@@ -4738,7 +4834,7 @@
"application/json": {
"schema": {
"type": "object",
- "description": "Slack Events API envelope — the shape depends on the event type"
+ "description": "Slack Events API envelope \u2014 the shape depends on the event type"
}
}
}
@@ -4762,12 +4858,13 @@
"404": {
"description": "Unknown platform"
}
- }
+ },
+ "security": []
}
},
"/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.",
+ "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 \u2014 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,
@@ -4775,7 +4872,10 @@
"application/json": {
"schema": {
"type": "object",
- "required": ["threadId", "status"],
+ "required": [
+ "threadId",
+ "status"
+ ],
"properties": {
"threadId": {
"type": "string",
@@ -4783,7 +4883,11 @@
},
"status": {
"type": "string",
- "enum": ["completed", "failed", "timeout"],
+ "enum": [
+ "completed",
+ "failed",
+ "timeout"
+ ],
"description": "Overall status of the content generation batch"
},
"results": {
@@ -4791,7 +4895,10 @@
"description": "Per-run results",
"items": {
"type": "object",
- "required": ["runId", "status"],
+ "required": [
+ "runId",
+ "status"
+ ],
"properties": {
"runId": {
"type": "string",
@@ -4799,7 +4906,11 @@
},
"status": {
"type": "string",
- "enum": ["completed", "failed", "timeout"]
+ "enum": [
+ "completed",
+ "failed",
+ "timeout"
+ ]
},
"videoUrl": {
"type": "string",
@@ -4855,128 +4966,1241 @@
}
]
}
- }
- },
- "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": {
+ },
+ "/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"
- },
- "description": "Optional custom email headers"
+ }
},
- "room_id": {
- "type": "string",
- "description": "Room ID to include a chat link in the email footer"
+ {
+ "name": "type",
+ "in": "query",
+ "required": false,
+ "description": "Entity type.",
+ "schema": {
+ "type": "string",
+ "enum": [
+ "artists",
+ "tracks",
+ "albums",
+ "playlists",
+ "curators",
+ "stations"
+ ],
+ "default": "artists"
+ }
},
- "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."
+ {
+ "name": "limit",
+ "in": "query",
+ "required": false,
+ "description": "Maximum number of results.",
+ "schema": {
+ "type": "integer",
+ "default": 10
+ }
}
- }
- },
- "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"
+ ],
+ "responses": {
+ "200": {
+ "description": "Search results",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ResearchSearchResponse"
+ }
+ }
+ }
}
}
- },
- "ConnectorInfo": {
- "type": "object",
- "required": [
- "slug",
- "name",
- "isConnected"
+ }
+ },
+ "/api/research/lookup": {
+ "get": {
+ "description": "Look up an artist by a platform URL or ID \u2014 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"
+ }
+ }
],
- "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)"
+ "responses": {
+ "200": {
+ "description": "Artist profile matching the platform URL",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ResearchLookupResponse"
+ }
+ }
+ }
}
}
- },
- "ConnectorsResponse": {
- "type": "object",
- "required": [
- "success",
- "connectors"
- ],
+ }
+ },
+ "/api/research/profile": {
+ "get": {
+ "description": "Get a full artist profile \u2014 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/metrics": {
+ "get": {
+ "description": "Get platform-specific metrics for an artist over time \u2014 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/audience": {
+ "get": {
+ "description": "Get audience demographics for an artist on a specific platform \u2014 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/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/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/urls": {
+ "get": {
+ "description": "Get all social and streaming URLs for an artist \u2014 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/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/playlists": {
+ "get": {
+ "description": "Get an artist's playlist placements \u2014 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/albums": {
+ "get": {
+ "description": "Get an artist's full discography \u2014 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/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/track": {
+ "get": {
+ "description": "Get track metadata \u2014 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/career": {
+ "get": {
+ "description": "Get an artist's career timeline \u2014 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/insights": {
+ "get": {
+ "description": "Get AI-generated insights about an artist \u2014 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/playlist": {
+ "get": {
+ "description": "Get playlist metadata \u2014 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/curator": {
+ "get": {
+ "description": "Get curator profile \u2014 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/discover": {
+ "get": {
+ "description": "Discover artists by criteria \u2014 filter by country, genre, listener count, follower count, growth rate, and more.",
+ "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/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/festivals": {
+ "get": {
+ "description": "List music festivals.",
+ "responses": {
+ "200": {
+ "description": "Festival list",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ResearchFestivalsResponse"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/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/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/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/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/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/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"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/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/people": {
+ "post": {
+ "description": "Search for people in the music industry \u2014 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/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/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"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "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"
@@ -6314,18 +7538,217 @@
"type": "integer",
"description": "Sum of posts across all platforms"
},
- "updated_at": {
+ "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"
+ }
+ }
+ },
+ "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",
- "format": "date-time",
- "description": "ISO timestamp of when the data was last updated"
+ "minLength": 3,
+ "maxLength": 50,
+ "description": "The new display name for the chat room. Must be between 3 and 50 characters."
}
}
},
- "ArtistProfileResponse": {
+ "UpdateChatResponse": {
"type": "object",
"required": [
"status",
- "profile"
+ "chat"
],
"properties": {
"status": {
@@ -6335,13 +7758,13 @@
],
"description": "Status of the request"
},
- "profile": {
- "$ref": "#/components/schemas/ArtistProfile",
- "description": "The artist's comprehensive profile information"
+ "chat": {
+ "$ref": "#/components/schemas/ChatRoom",
+ "description": "The updated chat room object"
}
}
},
- "ArtistProfileErrorResponse": {
+ "UpdateChatErrorResponse": {
"type": "object",
"required": [
"status",
@@ -6361,66 +7784,184 @@
}
}
},
- "ChatRoom": {
+ "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",
- "format": "uuid",
- "description": "UUID of the chat room"
+ "description": "Unique identifier for the message"
},
- "account_id": {
+ "role": {
"type": "string",
- "format": "uuid",
- "nullable": true,
- "description": "UUID of the associated account (can be null if not set)"
+ "enum": [
+ "user",
+ "assistant",
+ "system"
+ ],
+ "description": "The role of the message sender"
},
- "topic": {
+ "content": {
"type": "string",
- "nullable": true,
- "description": "Optional topic or description of the room (null if not provided)"
+ "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."
},
- "updated_at": {
+ "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": "date-time",
- "description": "ISO timestamp of the last update to the room"
+ "format": "uuid",
+ "description": "The unique identifier of the artist (optional)"
},
- "artist_id": {
+ "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",
- "nullable": true,
- "description": "UUID of the associated artist account (null when not applicable)"
+ "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)."
}
}
},
- "GetChatsResponse": {
+ "ContentPart": {
"type": "object",
- "required": [
- "status",
- "chats"
- ],
+ "description": "A part of the response content. See https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-text#content for details.",
"properties": {
- "status": {
+ "type": {
"type": "string",
"enum": [
- "success"
+ "text",
+ "tool-call",
+ "tool-result"
],
- "description": "Status of the request"
+ "description": "The type of content part"
},
- "chats": {
+ "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": {
- "$ref": "#/components/schemas/ChatRoom"
+ "type": "object"
},
- "description": "Array of chat room objects"
+ "description": "Response messages"
+ },
+ "headers": {
+ "type": "object",
+ "description": "Response headers"
+ },
+ "body": {
+ "type": "object",
+ "description": "Response body"
}
}
},
- "GetChatsErrorResponse": {
+ "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",
- "error"
+ "message"
],
"properties": {
"status": {
@@ -6430,57 +7971,59 @@
],
"description": "Status of the request"
},
- "error": {
+ "message": {
"type": "string",
"description": "Error message describing what went wrong"
}
}
},
- "CreateChatRequest": {
+ "ChatStreamRequest": {
"type": "object",
+ "description": "Request body for chat streaming. Exactly one of 'prompt' or 'messages' must be provided.",
"properties": {
- "artistId": {
+ "prompt": {
"type": "string",
- "format": "uuid",
- "description": "UUID of the artist account the chat is associated with"
+ "description": "Single text prompt for the assistant. Required if 'messages' is not provided."
},
- "chatId": {
- "type": "string",
- "format": "uuid",
- "description": "UUID for the new chat (client-generated). If not provided, one will be generated automatically."
+ "messages": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/UIMessage"
+ },
+ "description": "Array of UIMessage objects for context. Required if 'prompt' is not provided."
},
- "accountId": {
+ "artistId": {
"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."
+ "description": "The unique identifier of the artist (optional)"
},
- "topic": {
+ "model": {
"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": {
+ "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",
- "enum": [
- "success"
- ],
- "description": "Status of the request"
+ "format": "uuid",
+ "description": "UUID of the chat room. If not provided, one will be generated automatically."
},
- "chat": {
- "$ref": "#/components/schemas/ChatRoom",
- "description": "The created chat room object"
+ "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)."
}
}
},
- "CreateChatErrorResponse": {
+ "ChatStreamErrorResponse": {
"type": "object",
"required": [
"status",
@@ -6500,31 +8043,35 @@
}
}
},
- "UpdateChatRequest": {
+ "Organization": {
"type": "object",
- "required": [
- "chatId",
- "topic"
- ],
"properties": {
- "chatId": {
+ "id": {
"type": "string",
"format": "uuid",
- "description": "The unique identifier (UUID) of the chat room to update"
+ "description": "UUID of the membership record"
},
- "topic": {
+ "organization_id": {
"type": "string",
- "minLength": 3,
- "maxLength": 50,
- "description": "The new display name for the chat room. Must be between 3 and 50 characters."
+ "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"
}
}
},
- "UpdateChatResponse": {
+ "GetOrganizationsResponse": {
"type": "object",
"required": [
"status",
- "chat"
+ "organizations"
],
"properties": {
"status": {
@@ -6534,13 +8081,16 @@
],
"description": "Status of the request"
},
- "chat": {
- "$ref": "#/components/schemas/ChatRoom",
- "description": "The updated chat room object"
+ "organizations": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Organization"
+ },
+ "description": "List of organizations the account belongs to"
}
}
},
- "UpdateChatErrorResponse": {
+ "OrganizationsErrorResponse": {
"type": "object",
"required": [
"status",
@@ -6560,612 +8110,700 @@
}
}
},
- "UIMessage": {
+ "CreateOrganizationRequest": {
"type": "object",
- "description": "A message in the chat conversation. See https://ai-sdk.dev/docs/reference/ai-sdk-core/ui-message for details.",
+ "required": [
+ "name",
+ "accountId"
+ ],
"properties": {
- "id": {
- "type": "string",
- "description": "Unique identifier for the message"
- },
- "role": {
+ "name": {
"type": "string",
- "enum": [
- "user",
- "assistant",
- "system"
- ],
- "description": "The role of the message sender"
+ "description": "The name of the organization to create",
+ "example": "My New Label"
},
- "content": {
+ "accountId": {
"type": "string",
- "description": "The text content of the message"
+ "format": "uuid",
+ "description": "The account ID of the creator",
+ "example": "123e4567-e89b-12d3-a456-426614174000"
}
}
},
- "ChatGenerateRequest": {
+ "CreatedOrganization": {
"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": {
+ "id": {
"type": "string",
"format": "uuid",
- "description": "UUID of the chat room. If not provided, one will be generated automatically."
+ "description": "UUID of the new organization account"
},
- "topic": {
+ "name": {
"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)."
+ "description": "Name of the organization"
}
}
},
- "ContentPart": {
+ "CreateOrganizationResponse": {
"type": "object",
- "description": "A part of the response content. See https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-text#content for details.",
+ "required": [
+ "status",
+ "organization"
+ ],
"properties": {
- "type": {
+ "status": {
"type": "string",
"enum": [
- "text",
- "tool-call",
- "tool-result"
+ "success"
],
- "description": "The type of content part"
+ "description": "Status of the request"
},
- "text": {
- "type": "string",
- "description": "The text content (present when type is 'text')"
+ "organization": {
+ "$ref": "#/components/schemas/CreatedOrganization",
+ "description": "The created organization"
}
}
},
- "ChatGenerateUsage": {
+ "CreateWorkspaceRequest": {
"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)"
+ "name": {
+ "type": "string",
+ "description": "Name of the workspace (defaults to \"Untitled\")"
},
- "reasoningTokens": {
- "type": "integer",
- "description": "Number of reasoning tokens used"
+ "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."
},
- "cachedInputTokens": {
- "type": "integer",
- "description": "Number of cached input tokens"
+ "organization_id": {
+ "type": "string",
+ "format": "uuid",
+ "description": "Organization to link the workspace to"
}
}
},
- "ChatGenerateResponseMeta": {
+ "CreateWorkspaceResponse": {
"type": "object",
- "description": "Additional response metadata",
+ "required": [
+ "workspace"
+ ],
"properties": {
- "messages": {
- "type": "array",
- "items": {
- "type": "object"
- },
- "description": "Response messages"
- },
- "headers": {
- "type": "object",
- "description": "Response headers"
- },
- "body": {
+ "workspace": {
"type": "object",
- "description": "Response body"
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "name": {
+ "type": "string"
+ },
+ "account_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "isWorkspace": {
+ "type": "boolean"
+ }
+ }
}
}
},
- "ChatGenerateResponse": {
+ "AddArtistToOrganizationRequest": {
"type": "object",
- "description": "Response from the chat generation endpoint",
+ "required": [
+ "artistId",
+ "organizationId"
+ ],
"properties": {
- "text": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/ContentPart"
- },
- "description": "Array of content parts from the AI model response"
- },
- "reasoningText": {
+ "artistId": {
"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"
+ "format": "uuid",
+ "description": "The account ID of the artist to add",
+ "example": "artist-account-uuid"
},
- "finishReason": {
+ "organizationId": {
"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"
+ "format": "uuid",
+ "description": "The account ID of the organization",
+ "example": "org-account-uuid"
}
}
},
- "ChatGenerateErrorResponse": {
+ "AddArtistToOrganizationResponse": {
"type": "object",
"required": [
"status",
- "message"
+ "id"
],
"properties": {
"status": {
"type": "string",
"enum": [
- "error"
+ "success"
],
"description": "Status of the request"
},
- "message": {
+ "id": {
"type": "string",
- "description": "Error message describing what went wrong"
+ "format": "uuid",
+ "description": "UUID of the created artist-organization link"
}
}
},
- "ChatStreamRequest": {
+ "SpotifyImage": {
"type": "object",
- "description": "Request body for chat streaming. Exactly one of 'prompt' or 'messages' must be provided.",
"properties": {
- "prompt": {
+ "url": {
"type": "string",
- "description": "Single text prompt for the assistant. Required if 'messages' is not provided."
+ "description": "The source URL of the image"
},
- "messages": {
+ "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": {
- "$ref": "#/components/schemas/UIMessage"
+ "type": "string"
},
- "description": "Array of UIMessage objects for context. Required if 'prompt' is not provided."
+ "description": "A list of the genres the artist is associated with"
},
- "artistId": {
+ "href": {
"type": "string",
- "format": "uuid",
- "description": "The unique identifier of the artist (optional)"
+ "description": "A link to the Web API endpoint providing full details"
},
- "model": {
+ "id": {
"type": "string",
- "description": "The AI model to use for text generation (optional)",
- "example": "openai/gpt-5-mini"
+ "description": "The Spotify ID for the artist"
},
- "excludeTools": {
+ "images": {
"type": "array",
"items": {
- "type": "string"
+ "$ref": "#/components/schemas/SpotifyImage"
},
- "description": "Array of tool names to exclude from execution",
- "example": [
- "create_scheduled_actions"
- ]
+ "description": "Images of the artist in various sizes"
},
- "roomId": {
+ "name": {
"type": "string",
- "format": "uuid",
- "description": "UUID of the chat room. If not provided, one will be generated automatically."
+ "description": "The name of the artist"
},
- "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": {
+ "popularity": {
+ "type": "integer",
+ "description": "The popularity of the artist (0-100)"
+ },
+ "type": {
"type": "string",
"enum": [
- "error"
+ "artist"
],
- "description": "Status of the request"
+ "description": "The object type, always 'artist'"
},
- "message": {
+ "uri": {
"type": "string",
- "description": "Error message describing what went wrong"
+ "description": "The Spotify URI for the artist"
}
}
},
- "Organization": {
+ "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",
- "format": "uuid",
- "description": "UUID of the membership record"
+ "description": "The Spotify ID for the artist"
},
- "organization_id": {
+ "name": {
"type": "string",
- "format": "uuid",
- "description": "UUID of the organization account"
+ "description": "The name of the artist"
},
- "organization_name": {
+ "type": {
"type": "string",
- "description": "Display name of the organization"
+ "enum": [
+ "artist"
+ ],
+ "description": "The object type, always 'artist'"
},
- "organization_image": {
+ "uri": {
"type": "string",
- "nullable": true,
- "description": "Organization logo/image URL"
+ "description": "The Spotify URI for the artist"
}
}
},
- "GetOrganizationsResponse": {
+ "SpotifyArtistsPaginated": {
"type": "object",
- "required": [
- "status",
- "organizations"
- ],
"properties": {
- "status": {
+ "href": {
"type": "string",
- "enum": [
- "success"
- ],
- "description": "Status of the request"
+ "description": "A link to the Web API endpoint returning the full result"
},
- "organizations": {
+ "items": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/Organization"
+ "$ref": "#/components/schemas/SpotifyArtistObject"
},
- "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"
+ "description": "List of artist objects"
},
- "message": {
- "type": "string",
- "description": "Error message describing what went wrong"
- }
- }
- },
- "CreateOrganizationRequest": {
- "type": "object",
- "required": [
- "name",
- "accountId"
- ],
- "properties": {
- "name": {
+ "limit": {
+ "type": "integer",
+ "description": "The maximum number of items in the response"
+ },
+ "next": {
"type": "string",
- "description": "The name of the organization to create",
- "example": "My New Label"
+ "nullable": true,
+ "description": "URL to the next page of items"
},
- "accountId": {
+ "offset": {
+ "type": "integer",
+ "description": "The offset of the items returned"
+ },
+ "previous": {
"type": "string",
- "format": "uuid",
- "description": "The account ID of the creator",
- "example": "123e4567-e89b-12d3-a456-426614174000"
+ "nullable": true,
+ "description": "URL to the previous page of items"
+ },
+ "total": {
+ "type": "integer",
+ "description": "The total number of items available"
}
}
},
- "CreatedOrganization": {
+ "SpotifySearchResponse": {
"type": "object",
"properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "UUID of the new organization account"
+ "artists": {
+ "$ref": "#/components/schemas/SpotifyArtistsPaginated",
+ "description": "Search results for artists (if type includes artist)"
},
- "name": {
- "type": "string",
- "description": "Name of the organization"
+ "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)"
}
}
},
- "CreateOrganizationResponse": {
+ "SpotifyGetArtistResponse": {
"type": "object",
- "required": [
- "status",
- "organization"
- ],
"properties": {
- "status": {
- "type": "string",
- "enum": [
- "success"
- ],
- "description": "Status of the request"
+ "artist": {
+ "$ref": "#/components/schemas/SpotifyArtistObject",
+ "nullable": true,
+ "description": "The Spotify artist object (null if error)"
},
- "organization": {
- "$ref": "#/components/schemas/CreatedOrganization",
- "description": "The created organization"
+ "error": {
+ "type": "object",
+ "nullable": true,
+ "description": "Error object if request failed (null if successful)"
}
}
},
- "CreateWorkspaceRequest": {
+ "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": "Name of the workspace (defaults to \"Untitled\")"
+ "description": "The name of the album"
},
- "account_id": {
+ "release_date": {
"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."
+ "description": "The date the album was first released"
},
- "organization_id": {
+ "release_date_precision": {
"type": "string",
- "format": "uuid",
- "description": "Organization to link the workspace to"
- }
- }
- },
- "CreateWorkspaceResponse": {
- "type": "object",
- "required": [
- "workspace"
- ],
- "properties": {
- "workspace": {
+ "enum": [
+ "year",
+ "month",
+ "day"
+ ],
+ "description": "The precision with which release_date value is known"
+ },
+ "restrictions": {
"type": "object",
"properties": {
- "id": {
- "type": "string",
- "format": "uuid"
- },
- "name": {
- "type": "string"
- },
- "account_id": {
+ "reason": {
"type": "string",
- "format": "uuid"
- },
- "isWorkspace": {
- "type": "boolean"
+ "description": "The reason for the restriction"
}
- }
- }
- }
- },
- "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"
+ },
+ "description": "Included when a content restriction is applied"
},
- "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": {
"type": "string",
"enum": [
- "success"
+ "album"
],
- "description": "Status of the request"
+ "description": "The object type, always 'album'"
},
- "id": {
+ "uri": {
"type": "string",
- "format": "uuid",
- "description": "UUID of the created artist-organization link"
+ "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"
}
}
},
- "SpotifyImage": {
+ "SpotifyArtistAlbumsResponse": {
"type": "object",
"properties": {
- "url": {
+ "href": {
"type": "string",
- "description": "The source URL of the image"
+ "description": "A link to the Web API endpoint returning the full result"
},
- "height": {
+ "limit": {
"type": "integer",
+ "description": "The maximum number of items in the response"
+ },
+ "next": {
+ "type": "string",
"nullable": true,
- "description": "The image height in pixels"
+ "description": "URL to the next page of items"
},
- "width": {
+ "offset": {
"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": {
+ "description": "The offset of the items returned"
+ },
+ "previous": {
"type": "string",
"nullable": true,
- "description": "This will always be set to null"
+ "description": "URL to the previous page of items"
},
"total": {
"type": "integer",
- "description": "The total number of followers"
+ "description": "The total number of items available"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/SpotifySimplifiedAlbum"
+ },
+ "description": "Array of simplified album objects"
}
}
},
- "SpotifyArtistObject": {
+ "SpotifyTrack": {
"type": "object",
"properties": {
- "external_urls": {
- "$ref": "#/components/schemas/SpotifyExternalUrls"
+ "album": {
+ "$ref": "#/components/schemas/SpotifySimplifiedAlbum",
+ "description": "The album the track appears on"
},
- "followers": {
- "$ref": "#/components/schemas/SpotifyFollowers"
+ "artists": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/SpotifySimplifiedArtist"
+ },
+ "description": "Artists who performed the track"
},
- "genres": {
+ "available_markets": {
"type": "array",
"items": {
"type": "string"
},
- "description": "A list of the genres the artist is associated with"
+ "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": "A link to the Web API endpoint providing full details"
+ "description": "Link to the Web API endpoint with full details"
},
"id": {
"type": "string",
- "description": "The Spotify ID for the artist"
+ "description": "Spotify ID for the track"
},
- "images": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/SpotifyImage"
+ "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": "Images of the artist in various sizes"
+ "description": "Content restriction information"
},
"name": {
"type": "string",
- "description": "The name of the artist"
+ "description": "Track name"
},
"popularity": {
"type": "integer",
- "description": "The popularity of the artist (0-100)"
+ "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": [
- "artist"
+ "track"
],
- "description": "The object type, always 'artist'"
+ "description": "The object type, always 'track'"
},
"uri": {
"type": "string",
- "description": "The Spotify URI for the artist"
+ "description": "The Spotify URI for the track"
+ },
+ "is_local": {
+ "type": "boolean",
+ "description": "Whether the track is from a local file"
}
}
},
- "SpotifySimplifiedArtist": {
+ "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": "A link to the Web API endpoint providing full details"
+ "description": "Link to the Web API endpoint"
},
"id": {
"type": "string",
- "description": "The Spotify ID for the artist"
+ "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": "The name of the artist"
+ "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": [
- "artist"
- ],
- "description": "The object type, always 'artist'"
+ "track"
+ ]
},
"uri": {
"type": "string",
- "description": "The Spotify URI for the artist"
+ "description": "Spotify URI for the track"
+ },
+ "is_local": {
+ "type": "boolean",
+ "description": "Whether from a local file"
}
}
},
- "SpotifyArtistsPaginated": {
+ "SpotifyAlbumTracks": {
"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"
+ "description": "A link to the Web API endpoint"
},
"limit": {
"type": "integer",
@@ -7183,51 +8821,35 @@
"previous": {
"type": "string",
"nullable": true,
- "description": "URL to the previous page of items"
+ "description": "URL to the previous page"
},
"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)"
+ "description": "Total number of items available"
},
- "playlists": {
- "type": "object",
- "description": "Search results for playlists (if type includes playlist)"
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/SpotifySimplifiedTrack"
+ },
+ "description": "Array of simplified track objects"
}
}
},
- "SpotifyGetArtistResponse": {
+ "SpotifyCopyright": {
"type": "object",
"properties": {
- "artist": {
- "$ref": "#/components/schemas/SpotifyArtistObject",
- "nullable": true,
- "description": "The Spotify artist object (null if error)"
+ "text": {
+ "type": "string",
+ "description": "The copyright text"
},
- "error": {
- "type": "object",
- "nullable": true,
- "description": "Error object if request failed (null if successful)"
+ "type": {
+ "type": "string",
+ "description": "The type of copyright"
}
}
},
- "SpotifySimplifiedAlbum": {
+ "SpotifyAlbum": {
"type": "object",
"properties": {
"album_type": {
@@ -7276,738 +8898,831 @@
"type": "string",
"description": "The date the album was first released"
},
- "release_date_precision": {
+ "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",
- "enum": [
- "year",
- "month",
- "day"
- ],
- "description": "The precision with which release_date value is known"
+ "description": "The label associated with the album"
},
- "restrictions": {
+ "popularity": {
+ "type": "integer",
+ "description": "Popularity of the album (0-100)"
+ }
+ }
+ },
+ "SpotifyErrorResponse": {
+ "type": "object",
+ "properties": {
+ "error": {
"type": "object",
"properties": {
- "reason": {
+ "status": {
+ "type": "integer",
+ "description": "HTTP status code"
+ },
+ "message": {
"type": "string",
- "description": "The reason for the restriction"
+ "description": "Error message"
}
},
- "description": "Included when a content restriction is applied"
- },
- "type": {
+ "description": "Error details"
+ }
+ }
+ },
+ "TwitterPhoto": {
+ "type": "object",
+ "properties": {
+ "id": {
"type": "string",
- "enum": [
- "album"
- ],
- "description": "The object type, always 'album'"
+ "description": "Photo ID"
},
- "uri": {
+ "url": {
"type": "string",
- "description": "The Spotify URI for the album"
+ "description": "URL of the photo"
+ }
+ }
+ },
+ "TwitterVideo": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Video ID"
},
- "artists": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/SpotifySimplifiedArtist"
- },
- "description": "The artists of the album"
+ "preview": {
+ "type": "string",
+ "description": "URL of the video preview image"
},
- "album_group": {
+ "url": {
"type": "string",
- "enum": [
- "album",
- "single",
- "compilation",
- "appears_on"
- ],
- "description": "The field to distinguish albums by various groups"
+ "description": "URL of the video"
}
}
},
- "SpotifyArtistAlbumsResponse": {
+ "Tweet": {
"type": "object",
"properties": {
- "href": {
+ "id": {
"type": "string",
- "description": "A link to the Web API endpoint returning the full result"
+ "description": "Tweet ID"
},
- "limit": {
- "type": "integer",
- "description": "The maximum number of items in the response"
+ "text": {
+ "type": "string",
+ "description": "Tweet text content"
},
- "next": {
+ "username": {
"type": "string",
- "nullable": true,
- "description": "URL to the next page of items"
+ "description": "Username of the tweet author"
},
- "offset": {
+ "timestamp": {
"type": "integer",
- "description": "The offset of the items returned"
+ "description": "Unix timestamp (ms) of when the tweet was posted"
},
- "previous": {
+ "createdAt": {
"type": "string",
- "nullable": true,
- "description": "URL to the previous page of items"
+ "description": "ISO timestamp of when the tweet was posted"
},
- "total": {
+ "isReply": {
+ "type": "boolean",
+ "description": "Whether the tweet is a reply"
+ },
+ "isRetweet": {
+ "type": "boolean",
+ "description": "Whether the tweet is a retweet"
+ },
+ "likes": {
"type": "integer",
- "description": "The total number of items available"
+ "description": "Number of likes"
},
- "items": {
+ "retweetCount": {
+ "type": "integer",
+ "description": "Number of retweets"
+ },
+ "replies": {
+ "type": "integer",
+ "description": "Number of replies"
+ },
+ "photos": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/SpotifySimplifiedAlbum"
+ "$ref": "#/components/schemas/TwitterPhoto"
},
- "description": "Array of simplified album objects"
- }
- }
- },
- "SpotifyTrack": {
- "type": "object",
- "properties": {
- "album": {
- "$ref": "#/components/schemas/SpotifySimplifiedAlbum",
- "description": "The album the track appears on"
+ "description": "Array of photo objects"
},
- "artists": {
+ "videos": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/SpotifySimplifiedArtist"
+ "$ref": "#/components/schemas/TwitterVideo"
},
- "description": "Artists who performed the track"
+ "description": "Array of video objects"
},
- "available_markets": {
+ "urls": {
"type": "array",
"items": {
"type": "string"
},
- "description": "Markets in which the track is available"
+ "description": "Array of URLs included in the tweet"
},
- "disc_number": {
- "type": "integer",
- "description": "Disc number the track is on"
+ "permanentUrl": {
+ "type": "string",
+ "description": "Permanent URL to the tweet"
},
- "duration_ms": {
- "type": "integer",
- "description": "Track length in milliseconds"
+ "quotedStatusId": {
+ "type": "string",
+ "description": "ID of the quoted tweet (if applicable)"
},
- "explicit": {
- "type": "boolean",
- "description": "Whether the track has explicit lyrics"
+ "inReplyToStatusId": {
+ "type": "string",
+ "description": "ID of the tweet this is replying to (if applicable)"
},
- "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"
- }
+ "hashtags": {
+ "type": "array",
+ "items": {
+ "type": "string"
},
- "description": "Known external IDs for the track"
+ "description": "Array of hashtags in the tweet"
+ }
+ }
+ },
+ "TwitterSearchResponse": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "description": "Status of the request",
+ "enum": [
+ "success",
+ "error"
+ ]
},
- "external_urls": {
- "$ref": "#/components/schemas/SpotifyExternalUrls"
+ "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"
+ ]
},
- "href": {
+ "trends": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "List of current trending topics on Twitter"
+ }
+ }
+ },
+ "TwitterErrorResponse": {
+ "type": "object",
+ "properties": {
+ "status": {
"type": "string",
- "description": "Link to the Web API endpoint with full details"
+ "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",
- "description": "Spotify ID for the track"
- },
- "is_playable": {
- "type": "boolean",
- "description": "If true, the track is playable in the given market"
+ "format": "uuid",
+ "description": "UUID of the social's social_posts record"
},
- "linked_from": {
- "type": "object",
- "description": "Information about the originally requested track when track relinking is applied"
+ "post_id": {
+ "type": "string",
+ "format": "uuid",
+ "description": "UUID of the social's posts record"
},
- "restrictions": {
- "type": "object",
- "properties": {
- "reason": {
- "type": "string",
- "description": "The reason for the restriction"
- }
- },
- "description": "Content restriction information"
+ "social_id": {
+ "type": "string",
+ "format": "uuid",
+ "description": "UUID of the social's socials record"
},
- "name": {
+ "post_url": {
"type": "string",
- "description": "Track name"
+ "description": "Direct URL to the post on the platform"
},
- "popularity": {
+ "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": "Popularity score (0-100)"
+ "description": "Total number of posts available"
},
- "preview_url": {
- "type": "string",
- "nullable": true,
- "description": "URL to a 30 second preview, if available"
+ "page": {
+ "type": "integer",
+ "description": "Current page number"
},
- "track_number": {
+ "limit": {
"type": "integer",
- "description": "Track number on the album"
+ "description": "Number of posts per page"
},
- "type": {
+ "total_pages": {
+ "type": "integer",
+ "description": "Total number of pages available"
+ }
+ }
+ },
+ "SocialPostsResponse": {
+ "type": "object",
+ "properties": {
+ "status": {
"type": "string",
"enum": [
- "track"
+ "success",
+ "error"
],
- "description": "The object type, always 'track'"
+ "description": "Status of the request"
},
- "uri": {
- "type": "string",
- "description": "The Spotify URI for the track"
+ "posts": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/SocialPost"
+ },
+ "description": "List of social media posts"
},
- "is_local": {
- "type": "boolean",
- "description": "Whether the track is from a local file"
+ "pagination": {
+ "$ref": "#/components/schemas/SocialPostsPagination"
}
}
},
- "SpotifyArtistTopTracksResponse": {
+ "SocialErrorResponse": {
"type": "object",
"properties": {
- "tracks": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/SpotifyTrack"
- },
- "description": "Array of track objects"
+ "status": {
+ "type": "string",
+ "enum": [
+ "error"
+ ],
+ "description": "Status of the request"
+ },
+ "message": {
+ "type": "string",
+ "description": "Error message"
}
}
},
- "SpotifySimplifiedTrack": {
+ "GeneratedImage": {
"type": "object",
+ "description": "A generated image file from the AI model",
"properties": {
- "artists": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/SpotifySimplifiedArtist"
- },
- "description": "The artists who performed the track"
+ "base64": {
+ "type": "string",
+ "description": "Image file as a base64 encoded string"
},
- "available_markets": {
+ "uint8Array": {
"type": "array",
"items": {
- "type": "string"
+ "type": "integer"
},
- "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"
+ "description": "Image file as a Uint8Array (represented as array of numbers in JSON)"
},
- "href": {
+ "mediaType": {
"type": "string",
- "description": "Link to the Web API endpoint"
- },
- "id": {
+ "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": "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": {
+ "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": "Track name"
+ "description": "The AI model used for generation (e.g., 'dall-e-3', 'gpt-image-1')"
},
- "preview_url": {
+ "size": {
"type": "string",
- "nullable": true,
- "description": "URL to a 30 second preview"
- },
- "track_number": {
+ "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": "Track number on the album"
- },
- "type": {
- "type": "string",
- "enum": [
- "track"
- ]
+ "description": "Number of tokens used in the prompt"
},
- "uri": {
- "type": "string",
- "description": "Spotify URI for the track"
+ "completionTokens": {
+ "type": "integer",
+ "description": "Number of tokens used in the completion (typically 0 for image generation)"
},
- "is_local": {
- "type": "boolean",
- "description": "Whether from a local file"
+ "totalTokens": {
+ "type": "integer",
+ "description": "Total tokens used"
}
}
},
- "SpotifyAlbumTracks": {
+ "ArweaveTransaction": {
"type": "object",
+ "description": "Arweave transaction object for the stored image",
"properties": {
- "href": {
+ "id": {
"type": "string",
- "description": "A link to the Web API endpoint"
+ "description": "Unique identifier for the Arweave transaction"
},
- "limit": {
- "type": "integer",
- "description": "The maximum number of items in the response"
+ "last_tx": {
+ "type": "string",
+ "description": "Last transaction reference"
},
- "next": {
+ "owner": {
"type": "string",
- "nullable": true,
- "description": "URL to the next page of items"
+ "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)"
},
- "offset": {
- "type": "integer",
- "description": "The offset of the items returned"
+ "reward": {
+ "type": "string",
+ "description": "Mining reward for the transaction"
},
- "previous": {
+ "signature": {
"type": "string",
- "nullable": true,
- "description": "URL to the previous page"
+ "description": "Transaction signature"
},
- "total": {
+ "format": {
"type": "integer",
- "description": "Total number of items available"
- },
- "items": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/SpotifySimplifiedTrack"
- },
- "description": "Array of simplified track objects"
+ "description": "Transaction format version"
}
}
},
- "SpotifyCopyright": {
+ "InProcessMoment": {
"type": "object",
+ "description": "In Process moment metadata for provenance and ownership tracking",
"properties": {
- "text": {
+ "contractAddress": {
"type": "string",
- "description": "The copyright text"
+ "description": "Smart contract address for the moment"
},
- "type": {
+ "tokenId": {
"type": "string",
- "description": "The type of copyright"
+ "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)"
}
}
},
- "SpotifyAlbum": {
+ "ImageGenerationResponse": {
"type": "object",
+ "description": "Response from the image generation endpoint, extending Experimental_GenerateImageResult from the AI SDK",
"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"
+ "images": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/GeneratedImage"
+ },
+ "description": "Array of generated image objects"
},
- "available_markets": {
+ "warnings": {
"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"
+ "description": "Array of warning messages, if any"
},
- "images": {
+ "responses": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/SpotifyImage"
+ "$ref": "#/components/schemas/ImageResponseMeta"
},
- "description": "The cover art for the album in various sizes"
+ "description": "Array of response metadata from the AI provider"
},
- "name": {
- "type": "string",
- "description": "The name of the album"
+ "providerMetadata": {
+ "$ref": "#/components/schemas/ImageProviderMetadata"
},
- "release_date": {
- "type": "string",
- "description": "The date the album was first released"
+ "usage": {
+ "$ref": "#/components/schemas/ImageUsage"
},
- "release_date_precision": {
+ "imageUrl": {
"type": "string",
- "enum": [
- "year",
- "month",
- "day"
- ],
- "description": "The precision with which release_date value is known"
+ "description": "Permanent Arweave URL where the image is stored"
},
- "restrictions": {
- "type": "object",
- "properties": {
- "reason": {
- "type": "string"
- }
- },
- "description": "Included when a content restriction is applied"
+ "arweaveResult": {
+ "$ref": "#/components/schemas/ArweaveTransaction"
},
- "type": {
+ "moment": {
+ "$ref": "#/components/schemas/InProcessMoment"
+ }
+ }
+ },
+ "ImageGenerationErrorResponse": {
+ "type": "object",
+ "properties": {
+ "error": {
"type": "string",
- "enum": [
- "album"
- ],
- "description": "The object type, always 'album'"
- },
- "uri": {
+ "description": "Error message describing what went wrong"
+ }
+ }
+ },
+ "TranscribeAudioRequest": {
+ "type": "object",
+ "required": [
+ "audio_url",
+ "account_id",
+ "artist_account_id"
+ ],
+ "properties": {
+ "audio_url": {
"type": "string",
- "description": "The Spotify URI for the album"
- },
- "artists": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/SpotifySimplifiedArtist"
- },
- "description": "The artists of the album"
+ "description": "Public URL to the audio file (mp3, wav, m4a, webm)",
+ "example": "https://example.com/song.mp3"
},
- "tracks": {
- "$ref": "#/components/schemas/SpotifyAlbumTracks",
- "description": "The tracks of the album"
+ "account_id": {
+ "type": "string",
+ "format": "uuid",
+ "description": "Owner account ID for file storage",
+ "example": "550e8400-e29b-41d4-a716-446655440000"
},
- "copyrights": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/SpotifyCopyright"
- },
- "description": "Copyright statements of the album"
+ "artist_account_id": {
+ "type": "string",
+ "format": "uuid",
+ "description": "Artist account ID for file storage",
+ "example": "550e8400-e29b-41d4-a716-446655440001"
},
- "external_ids": {
- "type": "object",
- "properties": {
- "isrc": {
- "type": "string"
- },
- "ean": {
- "type": "string"
- },
- "upc": {
- "type": "string"
- }
- },
- "description": "Known external IDs for the album"
+ "title": {
+ "type": "string",
+ "description": "Optional title for the audio and transcription files",
+ "example": "My Song"
},
- "genres": {
- "type": "array",
- "items": {
- "type": "string"
- },
- "description": "Deprecated. Always empty."
+ "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"
},
- "label": {
+ "fileName": {
"type": "string",
- "description": "The label associated with the album"
+ "description": "Name of the saved file"
},
- "popularity": {
- "type": "integer",
- "description": "Popularity of the album (0-100)"
+ "storageKey": {
+ "type": "string",
+ "description": "Storage path in Supabase Storage"
}
}
},
- "SpotifyErrorResponse": {
+ "TranscribeAudioResponse": {
"type": "object",
+ "required": [
+ "success",
+ "audioFile",
+ "transcriptFile",
+ "text"
+ ],
"properties": {
- "error": {
- "type": "object",
- "properties": {
- "status": {
- "type": "integer",
- "description": "HTTP status code"
- },
- "message": {
- "type": "string",
- "description": "Error message"
- }
- },
- "description": "Error details"
+ "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')"
}
}
},
- "TwitterPhoto": {
+ "TranscribeAudioErrorResponse": {
"type": "object",
+ "required": [
+ "error"
+ ],
"properties": {
- "id": {
- "type": "string",
- "description": "Photo ID"
- },
- "url": {
+ "error": {
"type": "string",
- "description": "URL of the photo"
+ "description": "Error message describing what went wrong"
}
}
},
- "TwitterVideo": {
+ "SongArtist": {
"type": "object",
+ "description": "Artist associated with a song",
"properties": {
"id": {
"type": "string",
- "description": "Video ID"
+ "format": "uuid",
+ "description": "Unique identifier for the artist account"
},
- "preview": {
+ "name": {
"type": "string",
- "description": "URL of the video preview image"
+ "nullable": true,
+ "description": "Name of the artist (can be null)"
},
- "url": {
- "type": "string",
- "description": "URL of the video"
+ "timestamp": {
+ "type": "integer",
+ "nullable": true,
+ "description": "Timestamp associated with the artist account (can be null)"
}
}
},
- "Tweet": {
+ "Song": {
"type": "object",
+ "description": "A song with its metadata and associated artists",
"properties": {
- "id": {
- "type": "string",
- "description": "Tweet ID"
- },
- "text": {
- "type": "string",
- "description": "Tweet text content"
- },
- "username": {
+ "isrc": {
"type": "string",
- "description": "Username of the tweet author"
- },
- "timestamp": {
- "type": "integer",
- "description": "Unix timestamp (ms) of when the tweet was posted"
+ "description": "International Standard Recording Code (primary key)"
},
- "createdAt": {
+ "name": {
"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"
+ "description": "Name of the song"
},
- "permanentUrl": {
+ "album": {
"type": "string",
- "description": "Permanent URL to the tweet"
+ "description": "Name of the album the song belongs to"
},
- "quotedStatusId": {
+ "notes": {
"type": "string",
- "description": "ID of the quoted tweet (if applicable)"
+ "description": "Notes for the song"
},
- "inReplyToStatusId": {
+ "updated_at": {
"type": "string",
- "description": "ID of the tweet this is replying to (if applicable)"
+ "format": "date-time",
+ "description": "ISO timestamp of when the song data was last updated"
},
- "hashtags": {
+ "artists": {
"type": "array",
"items": {
- "type": "string"
+ "$ref": "#/components/schemas/SongArtist"
},
- "description": "Array of hashtags in the tweet"
+ "description": "Array of artist objects associated with this song"
}
}
},
- "TwitterSearchResponse": {
+ "SongsResponse": {
"type": "object",
+ "description": "Response containing songs data",
"properties": {
"status": {
"type": "string",
- "description": "Status of the request",
"enum": [
"success",
"error"
- ]
+ ],
+ "description": "Status of the request"
},
- "tweets": {
+ "songs": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/Tweet"
+ "$ref": "#/components/schemas/Song"
},
- "description": "List of tweet objects"
+ "description": "Array of song objects with artist information"
+ },
+ "error": {
+ "type": "string",
+ "description": "Error message (only present if status is 'error')"
}
}
},
- "TwitterTrendsResponse": {
+ "SongsErrorResponse": {
"type": "object",
"properties": {
"status": {
"type": "string",
- "description": "Status of the request",
"enum": [
- "success",
"error"
- ]
+ ],
+ "description": "Status of the request"
},
- "trends": {
- "type": "array",
- "items": {
- "type": "string"
- },
- "description": "List of current trending topics on Twitter"
+ "error": {
+ "type": "string",
+ "description": "Error message describing what went wrong"
}
}
},
- "TwitterErrorResponse": {
+ "CreateSongInput": {
"type": "object",
+ "required": [
+ "isrc"
+ ],
"properties": {
- "status": {
+ "isrc": {
"type": "string",
- "enum": [
- "error"
- ],
- "description": "Status of the request"
+ "description": "International Standard Recording Code of the song to create or fetch"
},
- "message": {
+ "name": {
"type": "string",
- "description": "Error message"
+ "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"
}
}
},
- "SocialScrapeRequest": {
+ "CreateSongsRequest": {
"type": "object",
"required": [
- "social_id"
+ "songs"
],
"properties": {
- "social_id": {
- "type": "string",
- "format": "uuid",
- "description": "UUID of the social profile to scrape. Obtain this from the Get Artist Socials API."
+ "songs": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/CreateSongInput"
+ },
+ "description": "Array of song inputs for bulk create/fetch"
}
}
},
- "SocialPost": {
+ "Catalog": {
"type": "object",
+ "description": "A catalog with its metadata",
"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"
+ "description": "Unique identifier for the catalog"
},
- "social_id": {
+ "name": {
"type": "string",
- "format": "uuid",
- "description": "UUID of the social's socials record"
+ "description": "Name of the catalog"
},
- "post_url": {
+ "created_at": {
"type": "string",
- "description": "Direct URL to the post on the platform"
+ "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 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"
+ "description": "ISO timestamp of when the catalog was last updated"
}
}
},
- "SocialPostsResponse": {
+ "CatalogsResponse": {
"type": "object",
+ "description": "Response containing catalogs data",
"properties": {
"status": {
"type": "string",
@@ -8017,19 +9732,20 @@
],
"description": "Status of the request"
},
- "posts": {
+ "catalogs": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/SocialPost"
+ "$ref": "#/components/schemas/Catalog"
},
- "description": "List of social media posts"
+ "description": "Array of catalog objects"
},
- "pagination": {
- "$ref": "#/components/schemas/SocialPostsPagination"
+ "error": {
+ "type": "string",
+ "description": "Error message (only present if status is 'error')"
}
}
},
- "SocialErrorResponse": {
+ "CatalogsErrorResponse": {
"type": "object",
"properties": {
"status": {
@@ -8039,378 +9755,371 @@
],
"description": "Status of the request"
},
- "message": {
+ "error": {
"type": "string",
- "description": "Error message"
+ "description": "Error message describing what went wrong"
}
}
},
- "GeneratedImage": {
+ "CreateCatalogInput": {
"type": "object",
- "description": "A generated image file from the AI model",
+ "required": [
+ "account_id"
+ ],
"properties": {
- "base64": {
+ "account_id": {
"type": "string",
- "description": "Image file as a base64 encoded string"
+ "format": "uuid",
+ "description": "The account to associate the catalog with"
},
- "uint8Array": {
- "type": "array",
- "items": {
- "type": "integer"
- },
- "description": "Image file as a Uint8Array (represented as array of numbers in JSON)"
+ "name": {
+ "type": "string",
+ "description": "Catalog name to create if catalog_id is omitted"
},
- "mediaType": {
+ "catalog_id": {
"type": "string",
- "description": "The IANA media type of the file (e.g., 'image/png', 'image/jpeg')"
+ "format": "uuid",
+ "description": "Existing catalog ID to link to the account"
}
}
},
- "ImageResponseMeta": {
+ "CreateCatalogsRequest": {
"type": "object",
- "description": "Response metadata from the AI provider",
+ "required": [
+ "catalogs"
+ ],
"properties": {
- "finishReason": {
- "type": "string",
- "description": "Reason the generation finished (e.g., 'stop')"
+ "catalogs": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/CreateCatalogInput"
+ },
+ "description": "Array of catalog inputs for bulk create/link operations"
}
}
},
- "ImageProviderMetadata": {
+ "DeleteCatalogInput": {
"type": "object",
- "description": "Metadata from the AI provider about the generation",
+ "required": [
+ "catalog_id",
+ "account_id"
+ ],
"properties": {
- "model": {
+ "catalog_id": {
"type": "string",
- "description": "The AI model used for generation (e.g., 'dall-e-3', 'gpt-image-1')"
+ "format": "uuid",
+ "description": "Catalog ID to remove"
},
- "size": {
+ "account_id": {
"type": "string",
- "description": "The size of the generated image (e.g., '1024x1024')"
+ "format": "uuid",
+ "description": "Account ID whose relationship will be removed"
}
}
},
- "ImageUsage": {
+ "DeleteCatalogsRequest": {
"type": "object",
- "description": "Token usage information for the image generation",
+ "required": [
+ "catalogs"
+ ],
"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"
+ "catalogs": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/DeleteCatalogInput"
+ },
+ "description": "Array of catalog-account pairs to remove"
}
}
},
- "ArweaveTransaction": {
+ "CatalogSong": {
"type": "object",
- "description": "Arweave transaction object for the stored image",
+ "description": "A song within a catalog with its metadata and associated artists",
"properties": {
- "id": {
- "type": "string",
- "description": "Unique identifier for the Arweave transaction"
- },
- "last_tx": {
- "type": "string",
- "description": "Last transaction reference"
- },
- "owner": {
+ "catalog_id": {
"type": "string",
- "description": "Owner address of the transaction"
- },
- "tags": {
- "type": "array",
- "items": {
- "type": "object"
- },
- "description": "Tags associated with the transaction"
+ "format": "uuid",
+ "description": "Catalog ID this song entry is associated with"
},
- "target": {
+ "isrc": {
"type": "string",
- "description": "Target address (empty for data transactions)"
+ "description": "International Standard Recording Code (primary key)"
},
- "quantity": {
+ "name": {
"type": "string",
- "description": "Amount transferred (typically '0' for data transactions)"
+ "description": "Name of the song"
},
- "data": {
+ "album": {
"type": "string",
- "description": "Transaction data (may be empty in response)"
+ "description": "Name of the album the song belongs to"
},
- "reward": {
+ "lyrics": {
"type": "string",
- "description": "Mining reward for the transaction"
+ "description": "Full lyrics of the song"
},
- "signature": {
+ "updated_at": {
"type": "string",
- "description": "Transaction signature"
+ "format": "date-time",
+ "description": "ISO timestamp of when the song data was last updated"
},
- "format": {
- "type": "integer",
- "description": "Transaction format version"
+ "artists": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/SongArtist"
+ },
+ "description": "Array of artist objects associated with this song"
}
}
},
- "InProcessMoment": {
+ "CatalogSongsPagination": {
"type": "object",
- "description": "In Process moment metadata for provenance and ownership tracking",
+ "description": "Pagination metadata for catalog songs response",
"properties": {
- "contractAddress": {
- "type": "string",
- "description": "Smart contract address for the moment"
+ "total_count": {
+ "type": "integer",
+ "description": "Total number of songs in the catalog"
},
- "tokenId": {
- "type": "string",
- "description": "Token ID of the minted moment"
+ "page": {
+ "type": "integer",
+ "description": "Current page number"
},
- "hash": {
- "type": "string",
- "description": "Transaction hash of the moment mint"
+ "limit": {
+ "type": "integer",
+ "description": "Number of songs per page"
},
- "chainId": {
+ "total_pages": {
"type": "integer",
- "description": "Chain ID (e.g., 8453 for Base)"
+ "description": "Total number of pages available"
}
}
},
- "ImageGenerationResponse": {
+ "CatalogSongsResponse": {
"type": "object",
- "description": "Response from the image generation endpoint, extending Experimental_GenerateImageResult from the AI SDK",
+ "description": "Response containing catalog songs data with pagination",
"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"
+ "status": {
+ "type": "string",
+ "enum": [
+ "success",
+ "error"
+ ],
+ "description": "Status of the request"
},
- "responses": {
+ "songs": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/ImageResponseMeta"
+ "$ref": "#/components/schemas/CatalogSong"
},
- "description": "Array of response metadata from the AI provider"
- },
- "providerMetadata": {
- "$ref": "#/components/schemas/ImageProviderMetadata"
+ "description": "Array of song objects with artist information"
},
- "usage": {
- "$ref": "#/components/schemas/ImageUsage"
+ "pagination": {
+ "$ref": "#/components/schemas/CatalogSongsPagination",
+ "description": "Pagination metadata for the response"
},
- "imageUrl": {
+ "error": {
"type": "string",
- "description": "Permanent Arweave URL where the image is stored"
- },
- "arweaveResult": {
- "$ref": "#/components/schemas/ArweaveTransaction"
- },
- "moment": {
- "$ref": "#/components/schemas/InProcessMoment"
+ "description": "Error message (only present if status is 'error')"
}
}
},
- "ImageGenerationErrorResponse": {
+ "CatalogSongsErrorResponse": {
"type": "object",
"properties": {
+ "status": {
+ "type": "string",
+ "enum": [
+ "error"
+ ],
+ "description": "Status of the request"
+ },
"error": {
"type": "string",
"description": "Error message describing what went wrong"
}
}
},
- "TranscribeAudioRequest": {
+ "AddCatalogSongInput": {
"type": "object",
"required": [
- "audio_url",
- "account_id",
- "artist_account_id"
+ "catalog_id",
+ "isrc"
],
"properties": {
- "audio_url": {
+ "catalog_id": {
"type": "string",
- "description": "Public URL to the audio file (mp3, wav, m4a, webm)",
- "example": "https://example.com/song.mp3"
+ "format": "uuid",
+ "description": "Catalog ID to which the song will be added"
},
- "account_id": {
+ "isrc": {
"type": "string",
- "format": "uuid",
- "description": "Owner account ID for file storage",
- "example": "550e8400-e29b-41d4-a716-446655440000"
+ "description": "Song ISRC to associate to the catalog"
},
- "artist_account_id": {
+ "name": {
"type": "string",
- "format": "uuid",
- "description": "Artist account ID for file storage",
- "example": "550e8400-e29b-41d4-a716-446655440001"
+ "description": "Optional. Applied only if internal search cannot find valid info for ISRC"
},
- "title": {
+ "album": {
"type": "string",
- "description": "Optional title for the audio and transcription files",
- "example": "My Song"
+ "description": "Optional. Applied only if internal search cannot find valid info for ISRC"
},
- "include_timestamps": {
- "type": "boolean",
- "description": "Whether to include timestamps in the markdown transcript",
- "default": false
+ "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"
}
}
},
- "TranscribeFileInfo": {
+ "AddCatalogSongsRequest": {
"type": "object",
+ "required": [
+ "songs"
+ ],
"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"
+ "songs": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/AddCatalogSongInput"
+ },
+ "description": "Array of songs for batch updates"
}
}
},
- "TranscribeAudioResponse": {
+ "DeleteCatalogSongInput": {
"type": "object",
"required": [
- "success",
- "audioFile",
- "transcriptFile",
- "text"
+ "catalog_id",
+ "isrc"
],
"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": {
+ "catalog_id": {
"type": "string",
- "description": "The full transcription text"
+ "format": "uuid",
+ "description": "Catalog ID from which the song will be removed"
},
- "language": {
+ "isrc": {
"type": "string",
- "description": "Detected language code (e.g., 'en', 'es', 'fr')"
+ "description": "Song ISRC to remove from the catalog"
}
}
},
- "TranscribeAudioErrorResponse": {
+ "DeleteCatalogSongsRequest": {
"type": "object",
"required": [
- "error"
+ "songs"
],
"properties": {
- "error": {
- "type": "string",
- "description": "Error message describing what went wrong"
+ "songs": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/DeleteCatalogSongInput"
+ },
+ "description": "Array of songs for batch deletes"
}
}
},
- "SongArtist": {
+ "ArtistFan": {
"type": "object",
- "description": "Artist associated with a song",
"properties": {
"id": {
"type": "string",
- "format": "uuid",
- "description": "Unique identifier for the artist account"
+ "description": "Unique identifier for the fan's social profile"
},
- "name": {
+ "username": {
"type": "string",
- "nullable": true,
- "description": "Name of the artist (can be null)"
+ "description": "Username or handle on the platform"
},
- "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": {
+ "avatar": {
"type": "string",
- "description": "International Standard Recording Code (primary key)"
+ "description": "URL to the fan's avatar/profile image"
},
- "name": {
+ "profile_url": {
"type": "string",
- "description": "Name of the song"
+ "description": "Full URL to the fan's profile on the platform"
},
- "album": {
+ "region": {
"type": "string",
- "description": "Name of the album the song belongs to"
+ "description": "Geographic region or location of the fan"
},
- "notes": {
+ "bio": {
"type": "string",
- "description": "Notes for the song"
+ "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 song data was last updated"
+ "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"
},
- "artists": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/SongArtist"
- },
- "description": "Array of artist objects associated with this song"
+ "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"
}
}
},
- "SongsResponse": {
+ "ArtistFansResponse": {
"type": "object",
- "description": "Response containing songs data",
+ "required": [
+ "status",
+ "fans",
+ "pagination"
+ ],
"properties": {
"status": {
"type": "string",
"enum": [
- "success",
- "error"
+ "success"
],
"description": "Status of the request"
},
- "songs": {
+ "fans": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/Song"
+ "$ref": "#/components/schemas/ArtistFan"
},
- "description": "Array of song objects with artist information"
+ "description": "List of social profiles from fans across all platforms"
},
- "error": {
- "type": "string",
- "description": "Error message (only present if status is 'error')"
+ "pagination": {
+ "$ref": "#/components/schemas/ArtistFansPagination",
+ "description": "Pagination metadata for the response"
}
}
},
- "SongsErrorResponse": {
+ "ArtistFansErrorResponse": {
"type": "object",
+ "required": [
+ "status",
+ "error"
+ ],
"properties": {
"status": {
"type": "string",
@@ -8425,104 +10134,137 @@
}
}
},
- "CreateSongInput": {
+ "SegmentFan": {
"type": "object",
- "required": [
- "isrc"
- ],
"properties": {
- "isrc": {
+ "id": {
"type": "string",
- "description": "International Standard Recording Code of the song to create or fetch"
+ "format": "uuid",
+ "description": "Unique identifier for the fan_segments record"
},
- "name": {
+ "username": {
"type": "string",
- "description": "Optional. Song name, applied only if internal search cannot find valid info"
+ "description": "Username or handle on the platform"
},
- "album": {
+ "avatar": {
"type": "string",
- "description": "Optional. Album name, applied only if internal search cannot find valid info"
+ "description": "URL to the fan's avatar/profile image"
},
- "notes": {
+ "profile_url": {
"type": "string",
- "description": "Optional. Notes for the song, applied only if internal search cannot find valid info"
+ "description": "Full URL to the fan's profile on the platform"
},
- "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"
+ "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"
}
}
},
- "Catalog": {
+ "ArtistPost": {
"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"
+ "description": "Unique identifier for the post"
},
- "created_at": {
+ "post_url": {
"type": "string",
- "format": "date-time",
- "description": "ISO timestamp of when the catalog was created"
+ "description": "Direct URL to the post on the social platform"
},
"updated_at": {
"type": "string",
"format": "date-time",
- "description": "ISO timestamp of when the catalog was last updated"
+ "description": "ISO timestamp of when the post was last updated"
}
}
},
- "CatalogsResponse": {
+ "ArtistPostsPagination": {
"type": "object",
- "description": "Response containing catalogs data",
+ "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",
- "error"
+ "success"
],
"description": "Status of the request"
},
- "catalogs": {
+ "posts": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/Catalog"
+ "$ref": "#/components/schemas/ArtistPost"
},
- "description": "Array of catalog objects"
+ "description": "List of posts from the artist across all social platforms"
},
- "error": {
- "type": "string",
- "description": "Error message (only present if status is 'error')"
+ "pagination": {
+ "$ref": "#/components/schemas/ArtistPostsPagination",
+ "description": "Pagination metadata for the response"
}
}
},
- "CatalogsErrorResponse": {
+ "ArtistPostsErrorResponse": {
"type": "object",
+ "required": [
+ "status",
+ "error"
+ ],
"properties": {
"status": {
"type": "string",
@@ -8537,123 +10279,186 @@
}
}
},
- "CreateCatalogInput": {
+ "PostComment": {
"type": "object",
"required": [
- "account_id"
+ "id",
+ "post_id",
+ "social_id",
+ "comment",
+ "commented_at",
+ "username",
+ "profile_url",
+ "post_url"
],
"properties": {
- "account_id": {
+ "id": {
"type": "string",
"format": "uuid",
- "description": "The account to associate the catalog with"
+ "description": "UUID of the comment record"
},
- "name": {
+ "post_id": {
"type": "string",
- "description": "Catalog name to create if catalog_id is omitted"
+ "format": "uuid",
+ "description": "UUID of the post this comment belongs to"
},
- "catalog_id": {
+ "social_id": {
"type": "string",
"format": "uuid",
- "description": "Existing catalog ID to link to the account"
+ "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"
}
}
},
- "CreateCatalogsRequest": {
+ "PostCommentsPagination": {
"type": "object",
- "required": [
- "catalogs"
- ],
"properties": {
- "catalogs": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/CreateCatalogInput"
- },
- "description": "Array of catalog inputs for bulk create/link operations"
+ "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"
}
}
},
- "DeleteCatalogInput": {
+ "PostCommentsResponse": {
"type": "object",
"required": [
- "catalog_id",
- "account_id"
+ "status",
+ "comments",
+ "pagination"
],
"properties": {
- "catalog_id": {
+ "status": {
"type": "string",
- "format": "uuid",
- "description": "Catalog ID to remove"
+ "enum": [
+ "success"
+ ],
+ "description": "Status of the request"
},
- "account_id": {
- "type": "string",
- "format": "uuid",
- "description": "Account ID whose relationship will be removed"
+ "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"
}
}
},
- "DeleteCatalogsRequest": {
+ "PostCommentsErrorResponse": {
"type": "object",
"required": [
- "catalogs"
+ "status",
+ "error"
],
"properties": {
- "catalogs": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/DeleteCatalogInput"
- },
- "description": "Array of catalog-account pairs to remove"
+ "status": {
+ "type": "string",
+ "enum": [
+ "error"
+ ],
+ "description": "Status of the request"
+ },
+ "error": {
+ "type": "string",
+ "description": "Error message describing what went wrong"
}
}
},
- "CatalogSong": {
+ "Comment": {
"type": "object",
- "description": "A song within a catalog with its metadata and associated artists",
"properties": {
- "catalog_id": {
+ "id": {
"type": "string",
"format": "uuid",
- "description": "Catalog ID this song entry is associated with"
- },
- "isrc": {
- "type": "string",
- "description": "International Standard Recording Code (primary key)"
+ "description": "UUID of the comment"
},
- "name": {
+ "post_id": {
"type": "string",
- "description": "Name of the song"
+ "format": "uuid",
+ "description": "UUID of the associated post"
},
- "album": {
+ "social_id": {
"type": "string",
- "description": "Name of the album the song belongs to"
+ "format": "uuid",
+ "description": "UUID of the social profile who made the comment"
},
- "lyrics": {
+ "comment": {
"type": "string",
- "description": "Full lyrics of the song"
+ "description": "Comment text content"
},
- "updated_at": {
+ "commented_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"
+ "description": "Timestamp with timezone of when the comment was made"
}
}
},
- "CatalogSongsPagination": {
+ "CommentsPagination": {
"type": "object",
- "description": "Pagination metadata for catalog songs response",
"properties": {
"total_count": {
"type": "integer",
- "description": "Total number of songs in the catalog"
+ "description": "Total number of comments available"
},
"page": {
"type": "integer",
@@ -8661,7 +10466,7 @@
},
"limit": {
"type": "integer",
- "description": "Number of songs per page"
+ "description": "Number of comments per page"
},
"total_pages": {
"type": "integer",
@@ -8669,37 +10474,40 @@
}
}
},
- "CatalogSongsResponse": {
+ "CommentsResponse": {
"type": "object",
- "description": "Response containing catalog songs data with pagination",
+ "required": [
+ "status",
+ "comments",
+ "pagination"
+ ],
"properties": {
"status": {
"type": "string",
"enum": [
- "success",
- "error"
+ "success"
],
"description": "Status of the request"
},
- "songs": {
+ "comments": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/CatalogSong"
+ "$ref": "#/components/schemas/Comment"
},
- "description": "Array of song objects with artist information"
+ "description": "List of comments for the specified artist or post"
},
"pagination": {
- "$ref": "#/components/schemas/CatalogSongsPagination",
+ "$ref": "#/components/schemas/CommentsPagination",
"description": "Pagination metadata for the response"
- },
- "error": {
- "type": "string",
- "description": "Error message (only present if status is 'error')"
}
}
},
- "CatalogSongsErrorResponse": {
+ "CommentsErrorResponse": {
"type": "object",
+ "required": [
+ "status",
+ "error"
+ ],
"properties": {
"status": {
"type": "string",
@@ -8714,161 +10522,239 @@
}
}
},
- "AddCatalogSongInput": {
+ "SegmentFansPagination": {
"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"
+ "total_count": {
+ "type": "integer",
+ "description": "Total number of records available"
},
- "album": {
- "type": "string",
- "description": "Optional. Applied only if internal search cannot find valid info for ISRC"
+ "page": {
+ "type": "integer",
+ "description": "Current page number"
},
- "notes": {
- "type": "string",
- "description": "Optional. Applied only if internal search cannot find valid info for ISRC"
+ "limit": {
+ "type": "integer",
+ "description": "Number of records per page"
},
- "artists": {
- "type": "array",
- "items": {
- "type": "string"
- },
- "description": "Optional array of artist names. Applied only if internal search lacks info"
+ "total_pages": {
+ "type": "integer",
+ "description": "Total number of pages available"
}
}
},
- "AddCatalogSongsRequest": {
+ "SegmentFansResponse": {
"type": "object",
"required": [
- "songs"
+ "status",
+ "fans",
+ "pagination"
],
"properties": {
- "songs": {
+ "status": {
+ "type": "string",
+ "enum": [
+ "success"
+ ],
+ "description": "Status of the request"
+ },
+ "fans": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/AddCatalogSongInput"
+ "$ref": "#/components/schemas/SegmentFan"
},
- "description": "Array of songs for batch updates"
+ "description": "List of social profiles from fans in the segment"
+ },
+ "pagination": {
+ "$ref": "#/components/schemas/SegmentFansPagination",
+ "description": "Pagination metadata for the response"
}
}
},
- "DeleteCatalogSongInput": {
+ "SegmentFansErrorResponse": {
"type": "object",
"required": [
- "catalog_id",
- "isrc"
+ "status",
+ "error"
],
"properties": {
- "catalog_id": {
+ "status": {
"type": "string",
- "format": "uuid",
- "description": "Catalog ID from which the song will be removed"
+ "enum": [
+ "error"
+ ],
+ "description": "Status of the request"
},
- "isrc": {
+ "error": {
"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"
+ "description": "Error message describing what went wrong"
}
}
},
- "ArtistFan": {
+ "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 fan's social profile"
+ "description": "Unique identifier for the subscription"
},
- "username": {
+ "object": {
"type": "string",
- "description": "Username or handle on the platform"
+ "enum": [
+ "subscription"
+ ],
+ "description": "String representing the object's type"
},
- "avatar": {
+ "customer": {
"type": "string",
- "description": "URL to the fan's avatar/profile image"
+ "description": "ID of the customer who owns this subscription"
},
- "profile_url": {
+ "status": {
"type": "string",
- "description": "Full URL to the fan's profile on the platform"
+ "enum": [
+ "active",
+ "canceled",
+ "incomplete",
+ "incomplete_expired",
+ "past_due",
+ "trialing",
+ "unpaid"
+ ],
+ "description": "The status of the subscription"
},
- "region": {
+ "currency": {
"type": "string",
- "description": "Geographic region or location of the fan"
+ "description": "Three-letter ISO currency code"
},
- "bio": {
- "type": "string",
- "description": "Fan's biography or profile description"
+ "current_period_start": {
+ "type": "integer",
+ "description": "Start of the current period (Unix timestamp)"
},
- "followerCount": {
+ "current_period_end": {
"type": "integer",
- "description": "Number of followers the fan has"
+ "description": "End of the current period (Unix timestamp)"
},
- "followingCount": {
+ "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": "Number of accounts the fan is following"
+ "description": "Time at which the subscription was created (Unix timestamp)"
},
- "updated_at": {
+ "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",
- "format": "date-time",
- "description": "ISO timestamp of when the fan data was last updated"
+ "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"
}
}
},
- "ArtistFansPagination": {
+ "SubscriptionResponse": {
"type": "object",
+ "required": [
+ "status",
+ "subscription"
+ ],
+ "description": "Response for standard accounts with Stripe subscriptions",
"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"
+ "status": {
+ "type": "string",
+ "enum": [
+ "success"
+ ],
+ "description": "Status of the request"
},
- "total_pages": {
- "type": "integer",
- "description": "Total number of pages available"
+ "subscription": {
+ "$ref": "#/components/schemas/StripeSubscription",
+ "description": "The full Stripe subscription object"
}
}
},
- "ArtistFansResponse": {
+ "EnterpriseSubscriptionResponse": {
"type": "object",
"required": [
"status",
- "fans",
- "pagination"
+ "isEnterprise"
],
+ "description": "Response for accounts with enterprise plans",
"properties": {
"status": {
"type": "string",
@@ -8877,20 +10763,16 @@
],
"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"
+ "isEnterprise": {
+ "type": "boolean",
+ "enum": [
+ true
+ ],
+ "description": "Indicates that the account has an enterprise plan"
}
}
},
- "ArtistFansErrorResponse": {
+ "SubscriptionErrorResponse": {
"type": "object",
"required": [
"status",
@@ -8910,109 +10792,219 @@
}
}
},
- "SegmentFan": {
+ "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": {
- "id": {
+ "command": {
"type": "string",
- "format": "uuid",
- "description": "Unique identifier for the fan_segments record"
+ "minLength": 1,
+ "description": "The command to execute in the sandbox environment. If omitted, the sandbox is created without running any command.",
+ "example": "ls"
},
- "username": {
- "type": "string",
- "description": "Username or handle on the platform"
+ "args": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Optional arguments to pass to the command.",
+ "example": [
+ "-la",
+ "/home"
+ ]
},
- "avatar": {
+ "cwd": {
"type": "string",
- "description": "URL to the fan's avatar/profile image"
+ "description": "Optional working directory for command execution.",
+ "example": "/home/user"
},
- "profile_url": {
+ "prompt": {
"type": "string",
- "description": "Full URL to the fan's profile on the platform"
+ "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"
},
- "segment_id": {
+ "account_id": {
"type": "string",
"format": "uuid",
- "description": "UUID of the fan's segments record"
+ "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"
},
- "segment_name": {
+ "sandboxStatus": {
"type": "string",
- "description": "Name of the segment (e.g., 'Twitter Followers')"
+ "enum": [
+ "pending",
+ "running",
+ "stopping",
+ "stopped",
+ "failed"
+ ],
+ "description": "Current lifecycle state of the sandbox",
+ "example": "running"
},
- "fan_social_id": {
+ "timeout": {
+ "type": "integer",
+ "description": "Milliseconds remaining before the sandbox stops automatically",
+ "example": 300000
+ },
+ "createdAt": {
"type": "string",
- "format": "uuid",
- "description": "UUID of the fan's socials media profile account"
+ "format": "date-time",
+ "description": "ISO 8601 timestamp when the sandbox was created",
+ "example": "2024-01-15T10:30:00.000Z"
},
- "region": {
+ "runId": {
"type": "string",
- "description": "Geographic region or location of the fan"
+ "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"
},
- "bio": {
+ "sandboxes": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Sandbox"
+ },
+ "description": "Array of sandbox objects"
+ },
+ "snapshot_id": {
"type": "string",
- "description": "Fan's biography or profile description"
+ "description": "The account's saved snapshot ID used for creating new sandboxes. Null if no snapshot has been saved.",
+ "example": "snap_abc123def456",
+ "nullable": true
},
- "follower_count": {
- "type": "integer",
- "description": "Number of followers the fan has"
+ "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
},
- "following_count": {
- "type": "integer",
- "description": "Number of accounts the fan is following"
+ "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"
+ }
},
- "updated_at": {
+ "error": {
"type": "string",
- "format": "date-time",
- "description": "ISO timestamp of when the fan data was last updated"
+ "description": "Error message (only present if status is error)"
}
}
},
- "ArtistPost": {
+ "SandboxErrorResponse": {
"type": "object",
+ "required": [
+ "error"
+ ],
"properties": {
- "id": {
+ "error": {
"type": "string",
- "format": "uuid",
- "description": "Unique identifier for the post"
- },
- "post_url": {
+ "description": "Error message describing what went wrong",
+ "example": "Failed to create sandbox"
+ }
+ }
+ },
+ "SandboxFileResponse": {
+ "type": "object",
+ "required": [
+ "status",
+ "content"
+ ],
+ "properties": {
+ "status": {
"type": "string",
- "description": "Direct URL to the post on the social platform"
+ "enum": [
+ "success"
+ ],
+ "description": "Status of the operation"
},
- "updated_at": {
+ "content": {
"type": "string",
- "format": "date-time",
- "description": "ISO timestamp of when the post was last updated"
+ "description": "The raw text content of the file"
}
}
},
- "ArtistPostsPagination": {
+ "UploadSandboxFilesRequest": {
"type": "object",
+ "required": [
+ "files"
+ ],
"properties": {
- "total_count": {
- "type": "integer",
- "description": "Total number of posts available"
- },
- "page": {
- "type": "integer",
- "description": "Current page number"
+ "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"
},
- "limit": {
- "type": "integer",
- "description": "Number of posts per page"
+ "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"
},
- "total_pages": {
- "type": "integer",
- "description": "Total number of pages available"
+ "message": {
+ "type": "string",
+ "description": "Optional commit message. Defaults to 'Upload files via API'.",
+ "example": "Add new album artwork"
}
}
},
- "ArtistPostsResponse": {
+ "UploadSandboxFilesResponse": {
"type": "object",
"required": [
"status",
- "posts",
- "pagination"
+ "uploaded"
],
"properties": {
"status": {
@@ -9020,242 +11012,495 @@
"enum": [
"success"
],
- "description": "Status of the request"
+ "description": "Status of the operation"
},
- "posts": {
+ "uploaded": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/ArtistPost"
+ "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": "List of posts from the artist across all social platforms"
- },
- "pagination": {
- "$ref": "#/components/schemas/ArtistPostsPagination",
- "description": "Pagination metadata for the response"
+ "description": "Array of uploaded file details"
}
}
},
- "ArtistPostsErrorResponse": {
+ "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",
- "error"
+ "runId"
],
"properties": {
"status": {
"type": "string",
"enum": [
- "error"
+ "success"
],
- "description": "Status of the request"
+ "description": "Status of the setup operation"
},
- "error": {
+ "runId": {
"type": "string",
- "description": "Error message describing what went wrong"
+ "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"
}
}
},
- "PostComment": {
+ "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": [
- "id",
- "post_id",
- "social_id",
- "comment",
- "commented_at",
- "username",
- "profile_url",
- "post_url"
+ "status"
],
"properties": {
- "id": {
+ "status": {
"type": "string",
- "format": "uuid",
- "description": "UUID of the comment record"
+ "enum": [
+ "success",
+ "error"
+ ],
+ "description": "Status of the delete operation"
},
- "post_id": {
- "type": "string",
- "format": "uuid",
- "description": "UUID of the post this comment belongs to"
+ "deleted_snapshot": {
+ "nullable": true,
+ "description": "The snapshot record that was deleted. Null if no snapshot existed for the account.",
+ "$ref": "#/components/schemas/UpdateSnapshotResponse"
},
- "social_id": {
+ "error": {
"type": "string",
- "format": "uuid",
- "description": "UUID of the social profile that made the comment"
- },
- "comment": {
+ "description": "Error message (only present if status is error)"
+ }
+ }
+ },
+ "UpdateSnapshotRequest": {
+ "type": "object",
+ "required": [],
+ "properties": {
+ "snapshotId": {
"type": "string",
- "description": "Text content of the comment"
+ "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"
},
- "commented_at": {
+ "github_repo": {
"type": "string",
- "format": "date-time",
- "description": "ISO timestamp of when the comment was posted"
+ "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"
},
- "username": {
+ "account_id": {
"type": "string",
- "description": "Username of the commenter"
- },
- "avatar": {
+ "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",
- "nullable": true,
- "description": "URL to the commenter's avatar image"
+ "format": "uuid",
+ "description": "The account ID this snapshot belongs to",
+ "example": "550e8400-e29b-41d4-a716-446655440000"
},
- "profile_url": {
+ "snapshot_id": {
"type": "string",
- "description": "URL to the commenter's profile"
+ "description": "The snapshot ID that was set for the account",
+ "example": "snap_abc123def456"
},
- "post_url": {
+ "expires_at": {
"type": "string",
- "description": "URL to the post where the comment was made"
+ "format": "date-time",
+ "description": "When the snapshot expires",
+ "example": "2027-01-01T00:00:00.000Z"
},
- "region": {
+ "github_repo": {
"type": "string",
"nullable": true,
- "description": "Geographic region of the commenter"
+ "description": "The GitHub repository URL associated with the sandbox",
+ "example": "https://github.com/org/repo"
},
- "bio": {
+ "created_at": {
"type": "string",
+ "format": "date-time",
"nullable": true,
- "description": "Commenter's biography or description"
+ "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"
},
- "follower_count": {
- "type": "integer",
- "nullable": true,
- "description": "Number of followers the commenter has"
+ "account_id": {
+ "type": "string",
+ "format": "uuid",
+ "description": "Unique identifier for the associated account"
},
- "following_count": {
- "type": "integer",
- "nullable": true,
- "description": "Number of accounts the commenter follows"
+ "active": {
+ "type": "boolean",
+ "description": "Whether the pulse is active (defaults to true)"
}
}
},
- "PostCommentsPagination": {
+ "PulseResponse": {
"type": "object",
+ "required": [
+ "status",
+ "pulse"
+ ],
"properties": {
- "total_count": {
- "type": "integer",
- "description": "Total number of comments available"
- },
- "page": {
- "type": "integer",
- "description": "Current page number"
+ "status": {
+ "type": "string",
+ "enum": [
+ "success",
+ "error"
+ ],
+ "description": "Status of the request"
},
- "limit": {
- "type": "integer",
- "description": "Number of comments per page"
+ "pulse": {
+ "$ref": "#/components/schemas/Pulse",
+ "description": "The pulse object"
},
- "total_pages": {
- "type": "integer",
- "description": "Total number of pages available"
+ "error": {
+ "type": "string",
+ "description": "Error message (only present if status is error)"
}
}
},
- "PostCommentsResponse": {
+ "PulsesResponse": {
"type": "object",
"required": [
"status",
- "comments",
- "pagination"
+ "pulses"
],
"properties": {
"status": {
"type": "string",
"enum": [
- "success"
+ "success",
+ "error"
],
"description": "Status of the request"
},
- "comments": {
+ "pulses": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/PostComment"
+ "$ref": "#/components/schemas/Pulse"
},
- "description": "List of comments for the specified post"
+ "description": "Array of pulse objects. Contains pulses for the authenticated account. If the account has access to organizations, all organization accounts are included."
},
- "pagination": {
- "$ref": "#/components/schemas/PostCommentsPagination",
- "description": "Pagination metadata for the response"
+ "error": {
+ "type": "string",
+ "description": "Error message (only present if status is error)"
}
}
},
- "PostCommentsErrorResponse": {
+ "UpdatePulseRequest": {
"type": "object",
"required": [
- "status",
- "error"
+ "active"
],
"properties": {
- "status": {
- "type": "string",
- "enum": [
- "error"
- ],
- "description": "Status of the request"
+ "active": {
+ "type": "boolean",
+ "description": "Whether to enable or disable the pulse",
+ "example": true
},
- "error": {
+ "account_id": {
"type": "string",
- "description": "Error message describing what went wrong"
+ "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."
}
}
},
- "Comment": {
+ "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",
- "format": "uuid",
- "description": "UUID of the comment"
+ "description": "The unique run identifier, prefixed with `run_`"
},
- "post_id": {
+ "status": {
"type": "string",
- "format": "uuid",
- "description": "UUID of the associated post"
+ "enum": [
+ "PENDING_VERSION",
+ "DELAYED",
+ "QUEUED",
+ "EXECUTING",
+ "REATTEMPTING",
+ "FROZEN",
+ "COMPLETED",
+ "CANCELED",
+ "FAILED",
+ "CRASHED",
+ "INTERRUPTED",
+ "SYSTEM_FAILURE"
+ ],
+ "description": "Current run status"
},
- "social_id": {
+ "taskIdentifier": {
"type": "string",
- "format": "uuid",
- "description": "UUID of the social profile who made the comment"
+ "description": "The task type identifier (e.g. 'setup-sandbox', 'run-sandbox-command')"
},
- "comment": {
+ "idempotencyKey": {
"type": "string",
- "description": "Comment text content"
+ "nullable": true,
+ "description": "Idempotency key used to deduplicate trigger requests"
},
- "commented_at": {
+ "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": "Timestamp with timezone of when the comment was made"
- }
- }
- },
- "CommentsPagination": {
- "type": "object",
- "properties": {
- "total_count": {
- "type": "integer",
- "description": "Total number of comments available"
+ "description": "When the run was created (ISO 8601)"
},
- "page": {
+ "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": "Current page number"
+ "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"
+ }
+ }
+ }
+ }
+ }
},
- "limit": {
- "type": "integer",
- "description": "Number of comments per page"
+ "schedule": {
+ "type": "object",
+ "nullable": true,
+ "description": "Schedule information if triggered by a schedule. Only present when retrieving by runId."
},
- "total_pages": {
- "type": "integer",
- "description": "Total number of pages available"
+ "relatedRuns": {
+ "type": "object",
+ "nullable": true,
+ "description": "Related run references (root, parent, children). Only present when retrieving by runId."
}
}
},
- "CommentsResponse": {
+ "TaskRunListResponse": {
"type": "object",
"required": [
"status",
- "comments",
- "pagination"
+ "runs"
],
"properties": {
"status": {
@@ -9263,704 +11508,737 @@
"enum": [
"success"
],
- "description": "Status of the request"
+ "description": "Indicates the request was successful"
},
- "comments": {
+ "runs": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/Comment"
+ "$ref": "#/components/schemas/TaskRunResponse"
},
- "description": "List of comments for the specified artist or post"
- },
- "pagination": {
- "$ref": "#/components/schemas/CommentsPagination",
- "description": "Pagination metadata for the response"
+ "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)."
}
}
},
- "CommentsErrorResponse": {
+ "FileTreeEntry": {
"type": "object",
"required": [
- "status",
- "error"
+ "path",
+ "type",
+ "sha"
],
+ "description": "A single entry in a GitHub repository file tree",
"properties": {
- "status": {
- "type": "string",
- "enum": [
- "error"
- ],
- "description": "Status of the request"
- },
- "error": {
+ "path": {
"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"
+ "description": "The file or directory path relative to the repository root",
+ "example": "src/index.ts"
},
- "total_pages": {
- "type": "integer",
- "description": "Total number of pages available"
- }
- }
- },
- "SegmentFansResponse": {
- "type": "object",
- "required": [
- "status",
- "fans",
- "pagination"
- ],
- "properties": {
- "status": {
+ "type": {
"type": "string",
"enum": [
- "success"
+ "blob",
+ "tree"
],
- "description": "Status of the request"
- },
- "fans": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/SegmentFan"
- },
- "description": "List of social profiles from fans in the segment"
+ "description": "The type of entry: blob for files, tree for directories"
},
- "pagination": {
- "$ref": "#/components/schemas/SegmentFansPagination",
- "description": "Pagination metadata for the response"
- }
- }
- },
- "SegmentFansErrorResponse": {
- "type": "object",
- "required": [
- "status",
- "error"
- ],
- "properties": {
- "status": {
+ "sha": {
"type": "string",
- "enum": [
- "error"
- ],
- "description": "Status of the request"
+ "description": "The SHA hash of the entry",
+ "example": "abc123def456"
},
- "error": {
- "type": "string",
- "description": "Error message describing what went wrong"
+ "size": {
+ "type": "integer",
+ "description": "The size of the file in bytes. Only present for blob entries.",
+ "example": 1024
}
}
},
- "StripeSubscription": {
+ "ContentCreateRequest": {
"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",
+ "description": "Parameters for triggering the content creation pipeline.",
"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": {
+ "artist_account_id": {
"type": "string",
- "enum": [
- "active",
- "canceled",
- "incomplete",
- "incomplete_expired",
- "past_due",
- "trialing",
- "unpaid"
- ],
- "description": "The status of the subscription"
+ "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"
},
- "currency": {
+ "template": {
"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)"
+ "description": "The template to use for content generation. Defines the visual style, scene, and prompt configuration. If omitted, defaults to `artist-caption-bedroom`. See [GET /api/content/templates](/api-reference/content/templates) for available options.",
+ "example": "artist-caption-stage",
+ "default": "artist-caption-bedroom"
},
- "cancel_at_period_end": {
+ "lipsync": {
"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"
- }
- }
+ "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
},
- "latest_invoice": {
+ "caption_length": {
"type": "string",
- "description": "ID of the most recent invoice for this subscription"
+ "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"
},
- "livemode": {
+ "upscale": {
"type": "boolean",
- "description": "Indicates if in live mode (true) or test mode (false)"
+ "description": "Whether to upscale the generated image and video using fal.ai SeedVR2 for higher resolution and detail. Adds approximately 2 minutes to the pipeline. Defaults to `false`.",
+ "default": false,
+ "example": false
},
- "metadata": {
- "type": "object",
- "description": "Set of key-value pairs attached to the subscription"
+ "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
}
- }
+ },
+ "required": [
+ "artist_account_id"
+ ]
},
- "SubscriptionResponse": {
+ "ContentCreateResponse": {
"type": "object",
"required": [
+ "runIds",
"status",
- "subscription"
+ "artist_account_id",
+ "template"
],
- "description": "Response for standard accounts with Stripe subscriptions",
+ "description": "Confirmation that the content creation pipeline has been triggered. Always returns `runIds` as an array \u2014 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": [
- "success"
+ "triggered"
],
- "description": "Status of the request"
+ "description": "Indicates the pipeline has been triggered"
},
- "subscription": {
- "$ref": "#/components/schemas/StripeSubscription",
- "description": "The full Stripe subscription object"
+ "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",
+ "description": "The template being used",
+ "example": "artist-caption-bedroom"
+ },
+ "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
}
}
},
- "EnterpriseSubscriptionResponse": {
+ "ContentCreateErrorResponse": {
"type": "object",
"required": [
- "status",
- "isEnterprise"
+ "error"
],
- "description": "Response for accounts with enterprise plans",
+ "description": "Returned when the artist is missing required files or the template is not found. Includes actionable instructions for resolving each issue.",
"properties": {
- "status": {
+ "error": {
"type": "string",
- "enum": [
- "success"
- ],
- "description": "Status of the request"
+ "description": "Human-readable error summary",
+ "example": "Artist 'new-artist' is not ready for content creation"
},
- "isEnterprise": {
+ "ready": {
"type": "boolean",
- "enum": [
- true
- ],
- "description": "Indicates that the account has an enterprise plan"
+ "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"
+ ]
}
}
},
- "SubscriptionErrorResponse": {
+ "ContentErrorResponse": {
"type": "object",
"required": [
- "status",
"error"
],
"properties": {
- "status": {
+ "error": {
"type": "string",
- "enum": [
- "error"
- ],
- "description": "Status of the request"
+ "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": [
+ "name",
+ "description",
+ "defaultLipsync"
+ ],
+ "description": "A content creation template that defines the visual style and composition for generated videos.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Template identifier. Pass this as the `template` field in [POST /api/content/create](/api-reference/content/create).",
+ "example": "artist-caption-bedroom"
},
- "error": {
+ "description": {
"type": "string",
- "description": "Error message describing what went wrong"
+ "description": "Human-readable description of the template's visual style",
+ "example": "Moody purple bedroom setting with caption overlay"
+ },
+ "defaultLipsync": {
+ "type": "boolean",
+ "description": "Whether this template defaults to lip-sync mode when the `lipsync` flag is not explicitly set",
+ "example": false
}
}
},
- "CreateSandboxRequest": {
+ "ContentValidateResponse": {
"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.",
+ "required": [
+ "ready",
+ "artist_account_id"
+ ],
+ "description": "Validation report for an artist's content creation readiness.",
"properties": {
- "command": {
+ "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",
- "minLength": 1,
- "description": "The command to execute in the sandbox environment. If omitted, the sandbox is created without running any command.",
- "example": "ls"
+ "format": "uuid",
+ "description": "UUID of the artist account that was validated",
+ "example": "1873859c-dd37-4e9a-9bac-80d3558527a9"
},
- "args": {
+ "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"
},
- "description": "Optional arguments to pass to the command.",
"example": [
- "-la",
- "/home"
+ "artist-caption-bedroom",
+ "artist-caption-outside",
+ "artist-caption-stage"
]
},
- "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"
+ "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"
+ },
+ "era_config": {
+ "$ref": "#/components/schemas/ContentValidationCheck"
+ },
+ "pipeline_config": {
+ "$ref": "#/components/schemas/ContentValidationCheck"
+ },
+ "songs": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/ContentValidationCheck"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "count": {
+ "type": "integer",
+ "description": "Number of songs found",
+ "example": 17
+ }
+ }
+ }
+ ]
+ }
+ }
},
- "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."
+ "missing": {
+ "type": "array",
+ "description": "List of missing files with severity and fix instructions. Only present when `ready` is `false`.",
+ "items": {
+ "$ref": "#/components/schemas/ContentMissingFile"
+ }
}
}
},
- "Sandbox": {
+ "ContentValidationCheck": {
"type": "object",
"required": [
- "sandboxId",
- "sandboxStatus",
- "timeout",
- "createdAt"
+ "status"
],
- "description": "A sandbox environment instance",
+ "description": "Status of a single validation check.",
"properties": {
- "sandboxId": {
- "type": "string",
- "description": "Unique identifier for the sandbox",
- "example": "sbx_abc123def456"
- },
- "sandboxStatus": {
+ "status": {
"type": "string",
"enum": [
- "pending",
- "running",
- "stopping",
- "stopped",
- "failed"
+ "ok",
+ "missing",
+ "warning"
],
- "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"
+ "description": "Whether the file was found",
+ "example": "ok"
}
}
},
- "SandboxesResponse": {
+ "ContentMissingFile": {
"type": "object",
"required": [
- "status",
- "sandboxes"
+ "file",
+ "severity",
+ "description",
+ "fix"
],
- "description": "Response containing sandbox information",
+ "description": "A missing file that prevents or degrades content creation.",
"properties": {
- "status": {
+ "file": {
"type": "string",
- "enum": [
- "success",
- "error"
- ],
- "description": "Status of the request"
- },
- "sandboxes": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Sandbox"
- },
- "description": "Array of sandbox objects"
+ "description": "Relative path of the missing file within the artist directory",
+ "example": "context/images/face-guide.png"
},
- "snapshot_id": {
+ "severity": {
"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
+ "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"
},
- "github_repo": {
+ "description": {
"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"
- }
+ "description": "What this file is used for in the pipeline",
+ "example": "Face guide image used for AI image generation"
},
- "error": {
+ "fix": {
"type": "string",
- "description": "Error message (only present if status is error)"
+ "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"
}
}
},
- "SandboxErrorResponse": {
+ "ContentEstimateResponse": {
"type": "object",
"required": [
- "error"
+ "workflows"
],
+ "description": "Cost estimates based on live fal.ai pricing. When `compare` is `false`, the `workflows` array contains a single entry. When `true`, it contains all available profiles.",
"properties": {
- "error": {
- "type": "string",
- "description": "Error message describing what went wrong",
- "example": "Failed to create sandbox"
+ "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
+ }
+ }
}
}
},
- "SandboxFileResponse": {
+ "ContentWorkflowEstimate": {
"type": "object",
"required": [
- "status",
- "content"
+ "name",
+ "perVideo",
+ "steps"
],
+ "description": "Cost breakdown for a single workflow profile.",
"properties": {
- "status": {
+ "name": {
"type": "string",
- "enum": [
- "success"
- ],
- "description": "Status of the operation"
+ "description": "Workflow profile name",
+ "example": "Current (image-to-video)"
},
- "content": {
- "type": "string",
- "description": "The raw text content of the file"
+ "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
+ }
+ }
}
}
},
- "UploadSandboxFilesRequest": {
+ "ContentStepEstimate": {
"type": "object",
"required": [
- "files"
+ "name",
+ "model",
+ "cost",
+ "note"
],
+ "description": "Cost details for a single pipeline step.",
"properties": {
- "path": {
+ "name": {
"type": "string",
- "description": "The target directory path within the repository to upload files to. Defaults to the repository root if omitted.",
- "example": "assets/images"
+ "description": "Pipeline step name",
+ "example": "Generate Image"
},
- "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"
+ "model": {
+ "type": "string",
+ "description": "The AI model or service used for this step",
+ "example": "fal-ai/nano-banana-pro/edit"
},
- "message": {
+ "cost": {
+ "type": "number",
+ "format": "float",
+ "description": "Estimated cost for this step in USD",
+ "example": 0.04
+ },
+ "unit": {
"type": "string",
- "description": "Optional commit message. Defaults to 'Upload files via API'.",
- "example": "Add new album artwork"
+ "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"
}
}
},
- "UploadSandboxFilesResponse": {
+ "ContentEstimateComparison": {
"type": "object",
"required": [
- "status",
- "uploaded"
+ "cheapest",
+ "cheapestPerVideo",
+ "mostExpensive",
+ "mostExpensivePerVideo",
+ "savingsPercent"
],
+ "description": "Summary comparing the cheapest and most expensive workflow options.",
"properties": {
- "status": {
+ "cheapest": {
"type": "string",
- "enum": [
- "success"
- ],
- "description": "Status of the operation"
+ "description": "Name of the cheapest workflow profile",
+ "example": "Budget (no upscale, LTX video)"
},
- "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"
+ "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
}
}
},
- "SetupSandboxRequest": {
+ "SongAnalyzeRequest": {
"type": "object",
+ "description": "Provide exactly one of `preset` or `prompt`. Use `preset` for structured analysis workflows, or `prompt` for free-form questions.",
"properties": {
- "account_id": {
+ "preset": {
"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."
+ "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 \u2014 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.0,
+ "description": "Controls output creativity \u2014 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
}
}
},
- "SetupSandboxResponse": {
+ "SongAnalyzeResponse": {
"type": "object",
- "required": [
- "status",
- "runId"
- ],
"properties": {
"status": {
"type": "string",
"enum": [
"success"
],
- "description": "Status of the setup operation"
+ "description": "Request status"
},
- "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": {
+ "preset": {
"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."
+ "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"
}
}
},
- "DeleteSandboxResponse": {
+ "SongAnalyzeErrorResponse": {
"type": "object",
- "required": [
- "status"
- ],
"properties": {
"status": {
"type": "string",
"enum": [
- "success",
"error"
],
- "description": "Status of the delete operation"
+ "description": "Error status"
},
- "deleted_snapshot": {
- "nullable": true,
- "description": "The snapshot record that was deleted. Null if no snapshot existed for the account.",
- "$ref": "#/components/schemas/UpdateSnapshotResponse"
+ "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 (only present if status is error)"
+ "description": "Error message describing what went wrong"
}
}
},
- "UpdateSnapshotRequest": {
+ "CheckAdminResponse": {
"type": "object",
- "required": [],
+ "required": [
+ "status",
+ "isAdmin"
+ ],
"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": {
+ "status": {
"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"
+ "enum": [
+ "success"
+ ],
+ "description": "Status of the request"
},
- "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."
+ "isAdmin": {
+ "type": "boolean",
+ "description": "Whether the authenticated account is a Recoup admin"
}
}
},
- "UpdateSnapshotResponse": {
+ "AccountSandboxRow": {
"type": "object",
"required": [
"account_id",
- "snapshot_id",
- "expires_at",
- "github_repo",
- "created_at"
+ "total_sandboxes",
+ "last_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"
+ "description": "The unique identifier of the account",
+ "example": "04e3aba9-c130-4fb8-8b92-34e95d43e66b"
},
- "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"
+ "total_sandboxes": {
+ "type": "integer",
+ "description": "Total number of sandboxes created for this account",
+ "example": 5
},
- "account_id": {
+ "last_created_at": {
"type": "string",
- "format": "uuid",
- "description": "Unique identifier for the associated account"
+ "format": "date-time",
+ "description": "ISO 8601 timestamp of the most recently created sandbox for this account",
+ "example": "2026-03-10T12:00:00Z"
},
- "active": {
- "type": "boolean",
- "description": "Whether the pulse is active (defaults to true)"
+ "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": ""
},
- "PulseResponse": {
+ "AdminSandboxesResponse": {
"type": "object",
"required": [
"status",
- "pulse"
+ "accounts"
],
+ "description": "Response containing per-account sandbox statistics for admin use",
"properties": {
"status": {
"type": "string",
@@ -9970,1303 +12248,1194 @@
],
"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)"
+ "accounts": {
+ "type": "array",
+ "description": "List of accounts with their sandbox statistics, ordered by most recently active first",
+ "items": {
+ "$ref": "#/components/schemas/AccountSandboxRow"
+ }
}
}
},
- "PulsesResponse": {
+ "OrgRepoRow": {
"type": "object",
"required": [
- "status",
- "pulses"
+ "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": {
- "status": {
+ "repo_name": {
"type": "string",
- "enum": [
- "success",
- "error"
- ],
- "description": "Status of the request"
+ "description": "Repository name",
+ "example": "chat"
},
- "pulses": {
+ "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": {
- "$ref": "#/components/schemas/Pulse"
+ "type": "string"
},
- "description": "Array of pulse objects. Contains pulses for the authenticated account. If the account has access to organizations, all organization accounts are included."
+ "example": [
+ "Merge test into main",
+ "fix: duration stuck at 0ms for in-progress tasks"
+ ]
},
- "error": {
+ "earliest_committed_at": {
"type": "string",
- "description": "Error message (only present if status is error)"
+ "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"
}
}
},
- "UpdatePulseRequest": {
+ "AdminEmailsResponse": {
"type": "object",
"required": [
- "active"
+ "status",
+ "emails"
],
+ "description": "Response containing Resend emails sent for an account",
"properties": {
- "active": {
- "type": "boolean",
- "description": "Whether to enable or disable the pulse",
- "example": true
- },
- "account_id": {
+ "status": {
"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."
+ "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"
+ }
}
}
},
- "TaskRunResponse": {
+ "PulseEmailRow": {
"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"
+ "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 unique run identifier, prefixed with `run_`"
+ "description": "The Resend email ID"
},
- "status": {
+ "from": {
"type": "string",
- "enum": [
- "PENDING_VERSION",
- "DELAYED",
- "QUEUED",
- "EXECUTING",
- "REATTEMPTING",
- "FROZEN",
- "COMPLETED",
- "CANCELED",
- "FAILED",
- "CRASHED",
- "INTERRUPTED",
- "SYSTEM_FAILURE"
- ],
- "description": "Current run status"
+ "description": "Sender email address"
},
- "taskIdentifier": {
- "type": "string",
- "description": "The task type identifier (e.g. 'setup-sandbox', 'run-sandbox-command')"
+ "to": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Recipient email addresses"
},
- "idempotencyKey": {
- "type": "string",
+ "cc": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
"nullable": true,
- "description": "Idempotency key used to deduplicate trigger requests"
+ "description": "CC recipient email addresses"
},
- "version": {
- "type": "string",
- "description": "The worker version that executed the run"
+ "bcc": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "nullable": true,
+ "description": "BCC recipient email addresses"
},
- "isTest": {
- "type": "boolean",
- "description": "Whether this is a test run"
+ "reply_to": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "nullable": true,
+ "description": "Reply-to email addresses"
},
- "createdAt": {
+ "subject": {
"type": "string",
- "format": "date-time",
- "description": "When the run was created (ISO 8601)"
+ "description": "Email subject line"
},
- "updatedAt": {
+ "html": {
"type": "string",
- "format": "date-time",
- "description": "When the run was last updated (ISO 8601)"
+ "nullable": true,
+ "description": "HTML content of the email"
},
- "startedAt": {
+ "text": {
"type": "string",
- "format": "date-time",
"nullable": true,
- "description": "When execution started (null if not yet started)"
+ "description": "Plain text content of the email"
},
- "finishedAt": {
+ "created_at": {
"type": "string",
"format": "date-time",
- "nullable": true,
- "description": "When the run finished (null if still running)"
+ "description": "Timestamp when the email was created"
},
- "delayedUntil": {
+ "scheduled_at": {
"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
+ "description": "Scheduled send time, if any"
},
- "expiredAt": {
+ "last_event": {
"type": "string",
- "format": "date-time",
- "nullable": true,
- "description": "When the run expired (null if not expired)"
+ "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": "string"
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "name",
+ "value"
+ ]
},
- "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"
+ "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"
},
- "durationMs": {
- "type": "number",
- "description": "Compute duration in milliseconds"
+ "repos": {
+ "type": "array",
+ "description": "List of org repos with their commit statistics, ordered by total_commits descending",
+ "items": {
+ "$ref": "#/components/schemas/OrgRepoRow"
+ }
+ }
+ }
+ },
+ "ResearchSearchResponse": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "enum": [
+ "success",
+ "error"
+ ]
},
- "env": {
- "type": "object",
- "description": "Environment the run executed in",
- "properties": {
- "id": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "user": {
- "type": "string",
- "nullable": true
- }
+ "results": {
+ "type": "array",
+ "description": "Matching artists with IDs, names, and basic metadata.",
+ "items": {
+ "$ref": "#/components/schemas/ResearchSearchResult"
}
+ }
+ }
+ },
+ "ResearchWebRequest": {
+ "type": "object",
+ "required": [
+ "query"
+ ],
+ "description": "Request body for web research.",
+ "properties": {
+ "query": {
+ "type": "string",
+ "description": "The search query \u2014 what you want to find on the web."
},
- "depth": {
+ "max_results": {
"type": "integer",
- "description": "Nesting depth for child runs"
+ "minimum": 1,
+ "maximum": 20,
+ "default": 10,
+ "description": "Maximum number of results to return."
},
- "batchId": {
+ "country": {
"type": "string",
- "nullable": true,
- "description": "Batch ID if triggered as part of a batch"
- },
- "triggerFunction": {
+ "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": [
- "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"
- }
- }
+ "success",
+ "error"
+ ]
},
- "attempts": {
+ "results": {
"type": "array",
- "description": "Attempt history. Only present when retrieving by runId.",
+ "description": "Ranked web search results.",
"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
+ "title": {
+ "type": "string"
},
- "completedAt": {
- "type": "string",
- "format": "date-time",
- "nullable": true
+ "url": {
+ "type": "string"
},
- "error": {
- "type": "object",
- "nullable": true,
- "properties": {
- "message": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "stackTrace": {
- "type": "string"
- }
- }
+ "content": {
+ "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."
+ "formatted": {
+ "type": "string",
+ "description": "Results formatted as markdown for easy reading."
}
}
},
- "TaskRunListResponse": {
+ "ResearchDeepRequest": {
"type": "object",
"required": [
- "status",
- "runs"
+ "query"
],
+ "description": "Request body for deep research. Performs comprehensive multi-source analysis.",
+ "properties": {
+ "query": {
+ "type": "string",
+ "description": "The research question \u2014 be specific and detailed for best results."
+ }
+ }
+ },
+ "ResearchDeepResponse": {
+ "type": "object",
+ "description": "Comprehensive research report with citations.",
"properties": {
"status": {
"type": "string",
"enum": [
- "success"
- ],
- "description": "Indicates the request was successful"
+ "success",
+ "error"
+ ]
},
- "runs": {
+ "content": {
+ "type": "string",
+ "description": "The full research report as markdown."
+ },
+ "citations": {
"type": "array",
+ "description": "Source URLs cited in the report.",
"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)."
+ "type": "string",
+ "format": "uri"
+ }
}
}
},
- "FileTreeEntry": {
+ "ResearchSearchResult": {
"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"
+ "name": {
+ "type": "string"
},
- "type": {
+ "id": {
+ "type": "integer",
+ "description": "Internal ID for use with other research endpoints."
+ },
+ "spotify_id": {
+ "type": "string",
+ "nullable": true
+ }
+ },
+ "additionalProperties": true
+ },
+ "ResearchProfileResponse": {
+ "type": "object",
+ "description": "Full artist profile \u2014 bio, genres, social links, label, images, and basic stats.",
+ "additionalProperties": true
+ },
+ "ResearchMetricsResponse": {
+ "type": "object",
+ "description": "Time-series metrics for a specific platform. Shape varies by source \u2014 typically an array of data points with timestamps and values (followers, listeners, views, etc.).",
+ "additionalProperties": true
+ },
+ "ResearchAudienceResponse": {
+ "type": "object",
+ "description": "Audience demographics breakdown \u2014 age ranges, gender split, and country distribution for the specified platform.",
+ "additionalProperties": true
+ },
+ "ResearchCitiesEntry": {
+ "type": "object",
+ "properties": {
+ "name": {
"type": "string",
- "enum": [
- "blob",
- "tree"
- ],
- "description": "The type of entry: blob for files, tree for directories"
+ "description": "City name."
},
- "sha": {
+ "country": {
"type": "string",
- "description": "The SHA hash of the entry",
- "example": "abc123def456"
+ "description": "ISO country code."
},
- "size": {
+ "listeners": {
"type": "integer",
- "description": "The size of the file in bytes. Only present for blob entries.",
- "example": 1024
+ "description": "Listener count in this city."
}
}
},
- "ContentCreateRequest": {
+ "ResearchCitiesResponse": {
"type": "object",
- "description": "Parameters for triggering the content creation pipeline.",
"properties": {
- "artist_account_id": {
+ "status": {
"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"
+ "enum": [
+ "success",
+ "error"
+ ]
},
- "template": {
- "type": "string",
- "description": "The template to use for content generation. Defines the visual style, scene, and prompt configuration. If omitted, defaults to `artist-caption-bedroom`. See [GET /api/content/templates](/api-reference/content/templates) for available options.",
- "example": "artist-caption-stage",
- "default": "artist-caption-bedroom"
+ "cities": {
+ "type": "array",
+ "description": "Cities ranked by listener concentration.",
+ "items": {
+ "$ref": "#/components/schemas/ResearchCitiesEntry"
+ }
+ }
+ }
+ },
+ "ResearchSimilarArtist": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
},
- "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
+ "id": {
+ "type": "integer"
},
- "caption_length": {
+ "similarity": {
+ "type": "number",
+ "description": "Similarity score (0-1)."
+ },
+ "career_stage": {
"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"
+ "description": "undiscovered, developing, mid-level, mainstream, superstar, or legendary."
},
- "upscale": {
- "type": "boolean",
- "description": "Whether to upscale the generated image and video using fal.ai SeedVR2 for higher resolution and detail. Adds approximately 2 minutes to the pipeline. Defaults to `false`.",
- "default": false,
- "example": false
+ "recent_momentum": {
+ "type": "string",
+ "description": "decline, gradual decline, steady, growth, or explosive growth."
},
- "batch": {
+ "sp_followers": {
"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
+ "nullable": true
+ },
+ "sp_monthly_listeners": {
+ "type": "integer",
+ "nullable": true
}
},
- "required": [
- "artist_account_id"
- ]
+ "additionalProperties": true
},
- "ContentCreateResponse": {
+ "ResearchSimilarResponse": {
"type": "object",
- "required": [
- "runIds",
- "status",
- "artist_account_id",
- "template"
- ],
- "description": "Confirmation that the content creation pipeline has been triggered. Always returns `runIds` as an array \u2014 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"
+ "success",
+ "error"
+ ]
},
- "artist_account_id": {
- "type": "string",
- "format": "uuid",
- "description": "UUID of the artist account the pipeline is running for",
- "example": "1873859c-dd37-4e9a-9bac-80d3558527a9"
+ "artists": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/ResearchSimilarArtist"
+ }
},
- "template": {
+ "total": {
+ "type": "integer"
+ }
+ }
+ },
+ "ResearchUrlEntry": {
+ "type": "object",
+ "properties": {
+ "domain": {
"type": "string",
- "description": "The template being used",
- "example": "artist-caption-bedroom"
- },
- "lipsync": {
- "type": "boolean",
- "description": "Whether lip-sync mode is enabled",
- "example": false
+ "description": "Platform name (e.g., spotify, instagram)."
},
- "failed": {
- "type": "integer",
- "description": "Number of triggers that failed. Only present when some triggers failed.",
- "example": 0
+ "url": {
+ "type": "string",
+ "format": "uri"
}
}
},
- "ContentCreateErrorResponse": {
+ "ResearchUrlsResponse": {
"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": {
+ "status": {
"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
+ "enum": [
+ "success",
+ "error"
+ ]
},
- "missing": {
+ "urls": {
"type": "array",
- "description": "List of missing files with severity and fix instructions. Only present when the artist fails validation.",
"items": {
- "$ref": "#/components/schemas/ContentMissingFile"
+ "$ref": "#/components/schemas/ResearchUrlEntry"
}
- },
- "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": {
+ "ResearchInstagramPostsResponse": {
+ "type": "object",
+ "description": "Top Instagram posts and reels sorted by engagement.",
+ "additionalProperties": true
+ },
+ "ResearchPlaylistPlacement": {
"type": "object",
- "required": [
- "error"
- ],
"properties": {
- "error": {
+ "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",
- "description": "Error message describing what went wrong",
- "example": "Unauthorized"
+ "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
},
- "ContentTemplatesResponse": {
+ "ResearchPlaylistsResponse": {
"type": "object",
- "required": [
- "templates"
- ],
- "description": "List of available content creation templates.",
"properties": {
- "templates": {
+ "status": {
+ "type": "string",
+ "enum": [
+ "success",
+ "error"
+ ]
+ },
+ "placements": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/ContentTemplate"
+ "$ref": "#/components/schemas/ResearchPlaylistPlacement"
}
}
}
},
- "ContentTemplate": {
+ "ResearchAlbum": {
"type": "object",
- "required": [
- "name",
- "description",
- "defaultLipsync"
- ],
- "description": "A content creation template that defines the visual style and composition for generated videos.",
"properties": {
"name": {
- "type": "string",
- "description": "Template identifier. Pass this as the `template` field in [POST /api/content/create](/api-reference/content/create).",
- "example": "artist-caption-bedroom"
+ "type": "string"
},
- "description": {
- "type": "string",
- "description": "Human-readable description of the template's visual style",
- "example": "Moody purple bedroom setting with caption overlay"
+ "id": {
+ "type": "integer"
},
- "defaultLipsync": {
- "type": "boolean",
- "description": "Whether this template defaults to lip-sync mode when the `lipsync` flag is not explicitly set",
- "example": false
+ "release_date": {
+ "type": "string",
+ "nullable": true
}
- }
+ },
+ "additionalProperties": true
},
- "ContentValidateResponse": {
+ "ResearchAlbumsResponse": {
"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": {
+ "status": {
"type": "string",
- "format": "uuid",
- "description": "UUID of the artist account that was validated",
- "example": "1873859c-dd37-4e9a-9bac-80d3558527a9"
+ "enum": [
+ "success",
+ "error"
+ ]
+ },
+ "albums": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/ResearchAlbum"
+ }
+ }
+ }
+ },
+ "ResearchTrackItem": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
},
- "songs": {
- "type": "integer",
- "description": "Number of songs found in the artist's `songs/` directory",
- "example": 17
+ "id": {
+ "type": "integer"
},
- "templates": {
+ "album_names": {
"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"
+ "nullable": true
+ }
+ },
+ "additionalProperties": true
+ },
+ "ResearchTracksResponse": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "enum": [
+ "success",
+ "error"
]
},
- "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"
- },
- "era_config": {
- "$ref": "#/components/schemas/ContentValidationCheck"
- },
- "pipeline_config": {
- "$ref": "#/components/schemas/ContentValidationCheck"
- },
- "songs": {
- "allOf": [
- {
- "$ref": "#/components/schemas/ContentValidationCheck"
- },
- {
- "type": "object",
- "properties": {
- "count": {
- "type": "integer",
- "description": "Number of songs found",
- "example": 17
- }
- }
- }
- ]
- }
- }
- },
- "missing": {
+ "tracks": {
"type": "array",
- "description": "List of missing files with severity and fix instructions. Only present when `ready` is `false`.",
"items": {
- "$ref": "#/components/schemas/ContentMissingFile"
+ "$ref": "#/components/schemas/ResearchTrackItem"
}
}
}
},
- "ContentValidationCheck": {
+ "ResearchTrackResponse": {
+ "type": "object",
+ "description": "Track metadata \u2014 title, artist, album, release date, popularity, and platform IDs.",
+ "additionalProperties": true
+ },
+ "ResearchCareerResponse": {
+ "type": "object",
+ "description": "Career timeline \u2014 milestones, trajectory, and career stage history.",
+ "additionalProperties": true
+ },
+ "ResearchInsight": {
+ "type": "object",
+ "properties": {
+ "text": {
+ "type": "string",
+ "description": "The insight text."
+ }
+ },
+ "additionalProperties": true
+ },
+ "ResearchInsightsResponse": {
"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"
+ "success",
+ "error"
+ ]
+ },
+ "insights": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/ResearchInsight"
+ }
}
}
},
- "ContentMissingFile": {
+ "ResearchPlaylistResponse": {
+ "type": "object",
+ "description": "Playlist metadata \u2014 name, description, follower count, track count, and curator info.",
+ "additionalProperties": true
+ },
+ "ResearchCuratorResponse": {
"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": {
+ "status": {
"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"
+ "success",
+ "error"
+ ]
},
- "description": {
- "type": "string",
- "description": "What this file is used for in the pipeline",
- "example": "Face guide image used for AI image generation"
+ "name": {
+ "type": "string"
},
- "fix": {
+ "id": {
+ "type": "integer"
+ },
+ "image_url": {
"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"
+ "format": "uri",
+ "nullable": true
+ },
+ "num_playlists": {
+ "type": "integer",
+ "nullable": true
+ },
+ "followers": {
+ "type": "integer",
+ "nullable": true
}
- }
+ },
+ "additionalProperties": true
},
- "ContentEstimateResponse": {
+ "ResearchDiscoverArtist": {
"type": "object",
- "required": [
- "workflows"
- ],
- "description": "Cost estimates based on live fal.ai 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"
- }
+ "name": {
+ "type": "string"
},
- "comparison": {
- "description": "Side-by-side summary. Only present when `compare` is `true` and multiple workflows are returned.",
- "$ref": "#/components/schemas/ContentEstimateComparison"
+ "id": {
+ "type": "integer"
},
- "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
- }
- }
+ "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
},
- "ContentWorkflowEstimate": {
+ "ResearchDiscoverResponse": {
"type": "object",
- "required": [
- "name",
- "perVideo",
- "steps"
- ],
- "description": "Cost breakdown for a single workflow profile.",
"properties": {
- "name": {
+ "status": {
"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
+ "enum": [
+ "success",
+ "error"
+ ]
},
- "steps": {
+ "artists": {
"type": "array",
- "description": "Per-step cost breakdown showing where the money goes",
"items": {
- "$ref": "#/components/schemas/ContentStepEstimate"
+ "$ref": "#/components/schemas/ResearchDiscoverArtist"
}
+ }
+ }
+ },
+ "ResearchGenre": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
},
- "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
- }
+ "id": {
+ "type": "integer"
+ }
+ }
+ },
+ "ResearchGenresResponse": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "enum": [
+ "success",
+ "error"
+ ]
+ },
+ "genres": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/ResearchGenre"
}
}
}
},
- "ContentStepEstimate": {
+ "ResearchFestival": {
"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
+ "type": "string"
},
- "unit": {
+ "city": {
"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
+ "nullable": true
},
- "note": {
+ "country": {
"type": "string",
- "description": "Human-readable calculation detail",
- "example": "1 call"
+ "nullable": true
}
- }
+ },
+ "additionalProperties": true
},
- "ContentEstimateComparison": {
+ "ResearchFestivalsResponse": {
"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": {
+ "status": {
"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
+ "enum": [
+ "success",
+ "error"
+ ]
},
- "savingsPercent": {
- "type": "integer",
- "description": "Percentage savings between the cheapest and most expensive workflows",
- "example": 81
+ "festivals": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/ResearchFestival"
+ }
}
}
},
- "SongAnalyzeRequest": {
+ "ResearchMilestone": {
"type": "object",
- "description": "Provide exactly one of `preset` or `prompt`. Use `preset` for structured analysis workflows, or `prompt` for free-form questions.",
"properties": {
- "preset": {
+ "date": {
"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"
+ "description": "Date of the milestone event."
},
- "prompt": {
+ "summary": {
"type": "string",
- "minLength": 1,
- "maxLength": 24000,
- "description": "Text prompt or question about the music",
- "example": "Describe the genre, tempo, and mood of this track."
+ "description": "Human-readable description of the event."
},
- "audio_url": {
+ "platform": {
"type": "string",
- "format": "uri",
- "description": "Public URL to an audio file (MP3, WAV, or FLAC \u2014 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.0,
- "description": "Controls output creativity \u2014 higher values produce more varied responses",
- "example": 0.7
+ "description": "Platform where the event occurred (e.g. spotify, apple_music)."
},
- "top_p": {
- "type": "number",
- "minimum": 0,
- "maximum": 1,
- "default": 1,
- "description": "Nucleus sampling probability cutoff",
- "example": 0.9
+ "track_name": {
+ "type": "string",
+ "description": "Name of the track involved, if any."
},
- "do_sample": {
- "type": "boolean",
- "default": false,
- "description": "Enable sampling (set true when using temperature or top_p)",
- "example": false
+ "stars": {
+ "type": "integer",
+ "description": "Importance rating (1-5 stars)."
}
}
},
- "SongAnalyzeResponse": {
+ "ResearchMilestonesResponse": {
"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"
+ "enum": ["success", "error"]
},
- "elapsed_seconds": {
- "type": "number",
- "format": "float",
- "description": "Inference time in seconds"
+ "milestones": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/ResearchMilestone"
+ }
}
}
},
- "SongAnalyzeErrorResponse": {
+ "ResearchVenue": {
"type": "object",
"properties": {
- "status": {
+ "venue_name": {
"type": "string",
- "enum": [
- "error"
- ],
- "description": "Error status"
+ "description": "Name of the venue."
},
- "missing_fields": {
+ "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": "Path to the first invalid or missing field when validation fails",
+ "description": "Events the artist performed at this venue.",
"items": {
- "type": "string"
+ "type": "object",
+ "additionalProperties": true
}
- },
- "error": {
- "type": "string",
- "description": "Error message describing what went wrong"
}
}
},
- "CheckAdminResponse": {
+ "ResearchVenuesResponse": {
"type": "object",
- "required": [
- "status",
- "isAdmin"
- ],
"properties": {
"status": {
"type": "string",
- "enum": [
- "success"
- ],
- "description": "Status of the request"
+ "enum": ["success", "error"]
},
- "isAdmin": {
- "type": "boolean",
- "description": "Whether the authenticated account is a Recoup admin"
+ "venues": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/ResearchVenue"
+ }
}
}
},
- "AccountSandboxRow": {
+ "ResearchRankResponse": {
"type": "object",
- "required": [
- "account_id",
- "total_sandboxes",
- "last_created_at"
- ],
"properties": {
- "account_id": {
+ "status": {
"type": "string",
- "format": "uuid",
- "description": "The unique identifier of the account",
- "example": "04e3aba9-c130-4fb8-8b92-34e95d43e66b"
+ "enum": ["success", "error"]
},
- "total_sandboxes": {
+ "rank": {
"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": "Global Chartmetric artist rank."
}
- },
- "description": ""
+ }
},
- "AdminSandboxesResponse": {
+ "ResearchChartsResponse": {
"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"
+ "enum": ["success", "error"]
+ },
+ "data": {
+ "type": "object",
+ "description": "Chart data — structure varies by platform.",
+ "additionalProperties": true
+ }
+ }
+ },
+ "ResearchRadioResponse": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "enum": ["success", "error"]
},
- "accounts": {
+ "stations": {
"type": "array",
- "description": "List of accounts with their sandbox statistics, ordered by most recently active first",
+ "description": "Radio stations tracked by Chartmetric.",
"items": {
- "$ref": "#/components/schemas/AccountSandboxRow"
+ "type": "object",
+ "additionalProperties": true
}
}
}
},
- "OrgRepoRow": {
+ "ResearchLookupResponse": {
+ "type": "object",
+ "description": "Artist profile resolved from a platform URL or ID.",
+ "additionalProperties": true
+ },
+ "ResearchPeopleRequest": {
"type": "object",
"required": [
- "repo_name",
- "repo_url",
- "total_commits",
- "latest_commit_messages",
- "earliest_committed_at",
- "latest_committed_at",
- "account_repos"
+ "query"
],
- "description": "Commit statistics for a single GitHub org repository",
"properties": {
- "repo_name": {
+ "query": {
"type": "string",
- "description": "Repository name",
- "example": "chat"
+ "description": "Natural language search for people (e.g., \"A&R reps at Atlantic Records\")."
},
- "repo_url": {
+ "num_results": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 100,
+ "default": 10,
+ "description": "Number of results to return."
+ }
+ }
+ },
+ "ResearchPeopleResult": {
+ "type": "object",
+ "properties": {
+ "title": {
"type": "string",
- "description": "Full GitHub HTML URL of the repository",
- "example": "https://github.com/recoupable/chat"
+ "description": "Person name and role."
},
- "total_commits": {
- "type": "integer",
- "description": "Total number of commits in the repository",
- "example": 5696
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "description": "Profile URL (often LinkedIn)."
},
- "latest_commit_messages": {
+ "highlights": {
"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"
+ "description": "Key excerpts from the profile."
},
- "latest_committed_at": {
+ "summary": {
"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"
+ "nullable": true,
+ "description": "Brief summary of the person."
}
}
},
- "AdminEmailsResponse": {
+ "ResearchPeopleResponse": {
"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": {
+ "results": {
"type": "array",
- "description": "List of emails sent for the account, ordered by created_at descending",
"items": {
- "$ref": "#/components/schemas/PulseEmailRow"
+ "$ref": "#/components/schemas/ResearchPeopleResult"
}
}
}
},
- "PulseEmailRow": {
+ "ResearchExtractRequest": {
"type": "object",
"required": [
- "id",
- "from",
- "to",
- "subject",
- "created_at",
- "last_event"
+ "urls"
],
- "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": {
+ "urls": {
"type": "array",
"items": {
- "type": "string"
+ "type": "string",
+ "format": "uri"
},
- "nullable": true,
- "description": "BCC recipient email addresses"
+ "maxItems": 10,
+ "description": "URLs to extract content from (max 10)."
},
- "reply_to": {
- "type": "array",
- "items": {
- "type": "string"
- },
- "nullable": true,
- "description": "Reply-to email addresses"
+ "objective": {
+ "type": "string",
+ "description": "What information to focus on (optional, max 3000 chars)."
},
- "subject": {
+ "full_content": {
+ "type": "boolean",
+ "default": false,
+ "description": "Return full page content instead of focused excerpts."
+ }
+ }
+ },
+ "ResearchExtractResult": {
+ "type": "object",
+ "properties": {
+ "url": {
"type": "string",
- "description": "Email subject line"
+ "format": "uri"
},
- "html": {
+ "title": {
"type": "string",
- "nullable": true,
- "description": "HTML content of the email"
+ "nullable": true
},
- "text": {
+ "publish_date": {
"type": "string",
"nullable": true,
- "description": "Plain text content of the email"
+ "description": "Publish date in YYYY-MM-DD format."
},
- "created_at": {
- "type": "string",
- "format": "date-time",
- "description": "Timestamp when the email was created"
+ "excerpts": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "nullable": true,
+ "description": "Focused excerpts as markdown."
},
- "scheduled_at": {
+ "full_content": {
"type": "string",
- "format": "date-time",
"nullable": true,
- "description": "Scheduled send time, if any"
- },
- "last_event": {
+ "description": "Full page content as markdown."
+ }
+ }
+ },
+ "ResearchExtractResponse": {
+ "type": "object",
+ "properties": {
+ "status": {
"type": "string",
"enum": [
- "bounced",
- "canceled",
- "clicked",
- "complained",
- "delivered",
- "delivery_delayed",
- "failed",
- "opened",
- "queued",
- "scheduled",
- "sent"
- ],
- "description": "Most recent delivery event for this email"
+ "success",
+ "error"
+ ]
},
- "tags": {
+ "results": {
"type": "array",
"items": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string"
- },
- "value": {
- "type": "string"
- }
- },
- "required": [
- "name",
- "value"
- ]
+ "$ref": "#/components/schemas/ResearchExtractResult"
+ }
+ },
+ "errors": {
+ "type": "array",
+ "items": {
+ "type": "object"
},
- "nullable": true,
- "description": "Custom tags attached to the email"
+ "description": "URLs that failed to extract."
}
}
},
- "AdminSandboxOrgsResponse": {
+ "ResearchEnrichRequest": {
"type": "object",
"required": [
- "status",
- "repos"
+ "input",
+ "schema"
],
- "description": "Response containing commit statistics for all org repositories",
+ "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"
- ],
- "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"
+ "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."
+ }
+ }
+ }
+ }
}
}
}
@@ -11282,7 +13451,13 @@
"in": "header",
"name": "x-api-key",
"description": "Your Recoup API key. [Learn more](/quickstart#api-keys)."
+ },
+ "callbackSecret": {
+ "type": "apiKey",
+ "in": "header",
+ "name": "x-callback-secret",
+ "description": "Shared secret used by internal Trigger.dev callback requests."
}
}
}
-}
+}
\ No newline at end of file
diff --git a/api-reference/research/albums.mdx b/api-reference/research/albums.mdx
new file mode 100644
index 0000000..ad026fd
--- /dev/null
+++ b/api-reference/research/albums.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Albums'
+openapi: 'GET /api/research/albums'
+---
diff --git a/api-reference/research/audience.mdx b/api-reference/research/audience.mdx
new file mode 100644
index 0000000..9a4b73f
--- /dev/null
+++ b/api-reference/research/audience.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Audience Demographics'
+openapi: 'GET /api/research/audience'
+---
diff --git a/api-reference/research/career.mdx b/api-reference/research/career.mdx
new file mode 100644
index 0000000..2544ff3
--- /dev/null
+++ b/api-reference/research/career.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Career Timeline'
+openapi: 'GET /api/research/career'
+---
diff --git a/api-reference/research/charts.mdx b/api-reference/research/charts.mdx
new file mode 100644
index 0000000..25dead0
--- /dev/null
+++ b/api-reference/research/charts.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Charts'
+openapi: 'GET /api/research/charts'
+---
diff --git a/api-reference/research/cities.mdx b/api-reference/research/cities.mdx
new file mode 100644
index 0000000..d379fa4
--- /dev/null
+++ b/api-reference/research/cities.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Listener Cities'
+openapi: 'GET /api/research/cities'
+---
diff --git a/api-reference/research/curator.mdx b/api-reference/research/curator.mdx
new file mode 100644
index 0000000..7761c0c
--- /dev/null
+++ b/api-reference/research/curator.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Curator'
+openapi: 'GET /api/research/curator'
+---
diff --git a/api-reference/research/deep.mdx b/api-reference/research/deep.mdx
new file mode 100644
index 0000000..34bb0f3
--- /dev/null
+++ b/api-reference/research/deep.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Deep Research'
+openapi: 'POST /api/research/deep'
+---
diff --git a/api-reference/research/discover.mdx b/api-reference/research/discover.mdx
new file mode 100644
index 0000000..c5c643e
--- /dev/null
+++ b/api-reference/research/discover.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Discover Artists'
+openapi: 'GET /api/research/discover'
+---
diff --git a/api-reference/research/enrich.mdx b/api-reference/research/enrich.mdx
new file mode 100644
index 0000000..5d6a769
--- /dev/null
+++ b/api-reference/research/enrich.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Enrich'
+openapi: 'POST /api/research/enrich'
+---
diff --git a/api-reference/research/extract.mdx b/api-reference/research/extract.mdx
new file mode 100644
index 0000000..40733c3
--- /dev/null
+++ b/api-reference/research/extract.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Extract URL'
+openapi: 'POST /api/research/extract'
+---
diff --git a/api-reference/research/festivals.mdx b/api-reference/research/festivals.mdx
new file mode 100644
index 0000000..97b3c0b
--- /dev/null
+++ b/api-reference/research/festivals.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Festivals'
+openapi: 'GET /api/research/festivals'
+---
diff --git a/api-reference/research/genres.mdx b/api-reference/research/genres.mdx
new file mode 100644
index 0000000..12b7795
--- /dev/null
+++ b/api-reference/research/genres.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Genres'
+openapi: 'GET /api/research/genres'
+---
diff --git a/api-reference/research/insights.mdx b/api-reference/research/insights.mdx
new file mode 100644
index 0000000..88695cf
--- /dev/null
+++ b/api-reference/research/insights.mdx
@@ -0,0 +1,4 @@
+---
+title: 'AI Insights'
+openapi: 'GET /api/research/insights'
+---
diff --git a/api-reference/research/instagram-posts.mdx b/api-reference/research/instagram-posts.mdx
new file mode 100644
index 0000000..9d598de
--- /dev/null
+++ b/api-reference/research/instagram-posts.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Instagram Posts'
+openapi: 'GET /api/research/instagram-posts'
+---
diff --git a/api-reference/research/lookup.mdx b/api-reference/research/lookup.mdx
new file mode 100644
index 0000000..bda5bc2
--- /dev/null
+++ b/api-reference/research/lookup.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Lookup by URL'
+openapi: 'GET /api/research/lookup'
+---
diff --git a/api-reference/research/metrics.mdx b/api-reference/research/metrics.mdx
new file mode 100644
index 0000000..ff1b706
--- /dev/null
+++ b/api-reference/research/metrics.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Platform Metrics'
+openapi: 'GET /api/research/metrics'
+---
diff --git a/api-reference/research/milestones.mdx b/api-reference/research/milestones.mdx
new file mode 100644
index 0000000..c11f762
--- /dev/null
+++ b/api-reference/research/milestones.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Milestones'
+openapi: 'GET /api/research/milestones'
+---
diff --git a/api-reference/research/people.mdx b/api-reference/research/people.mdx
new file mode 100644
index 0000000..06b6d0a
--- /dev/null
+++ b/api-reference/research/people.mdx
@@ -0,0 +1,4 @@
+---
+title: 'People Search'
+openapi: 'POST /api/research/people'
+---
diff --git a/api-reference/research/playlist.mdx b/api-reference/research/playlist.mdx
new file mode 100644
index 0000000..0da706e
--- /dev/null
+++ b/api-reference/research/playlist.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Playlist'
+openapi: 'GET /api/research/playlist'
+---
diff --git a/api-reference/research/playlists.mdx b/api-reference/research/playlists.mdx
new file mode 100644
index 0000000..dce5080
--- /dev/null
+++ b/api-reference/research/playlists.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Playlist Placements'
+openapi: 'GET /api/research/playlists'
+---
diff --git a/api-reference/research/profile.mdx b/api-reference/research/profile.mdx
new file mode 100644
index 0000000..1331b9a
--- /dev/null
+++ b/api-reference/research/profile.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Artist Profile'
+openapi: 'GET /api/research/profile'
+---
diff --git a/api-reference/research/radio.mdx b/api-reference/research/radio.mdx
new file mode 100644
index 0000000..6115267
--- /dev/null
+++ b/api-reference/research/radio.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Radio Stations'
+openapi: 'GET /api/research/radio'
+---
diff --git a/api-reference/research/rank.mdx b/api-reference/research/rank.mdx
new file mode 100644
index 0000000..a9fb36b
--- /dev/null
+++ b/api-reference/research/rank.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Artist Rank'
+openapi: 'GET /api/research/rank'
+---
diff --git a/api-reference/research/search.mdx b/api-reference/research/search.mdx
new file mode 100644
index 0000000..ab64614
--- /dev/null
+++ b/api-reference/research/search.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Search'
+openapi: 'GET /api/research'
+---
diff --git a/api-reference/research/similar.mdx b/api-reference/research/similar.mdx
new file mode 100644
index 0000000..623c4b8
--- /dev/null
+++ b/api-reference/research/similar.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Similar Artists'
+openapi: 'GET /api/research/similar'
+---
diff --git a/api-reference/research/track.mdx b/api-reference/research/track.mdx
new file mode 100644
index 0000000..cf1b522
--- /dev/null
+++ b/api-reference/research/track.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Track'
+openapi: 'GET /api/research/track'
+---
diff --git a/api-reference/research/tracks.mdx b/api-reference/research/tracks.mdx
new file mode 100644
index 0000000..037ea66
--- /dev/null
+++ b/api-reference/research/tracks.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Tracks'
+openapi: 'GET /api/research/tracks'
+---
diff --git a/api-reference/research/urls.mdx b/api-reference/research/urls.mdx
new file mode 100644
index 0000000..54196e8
--- /dev/null
+++ b/api-reference/research/urls.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Social URLs'
+openapi: 'GET /api/research/urls'
+---
diff --git a/api-reference/research/venues.mdx b/api-reference/research/venues.mdx
new file mode 100644
index 0000000..06f0d22
--- /dev/null
+++ b/api-reference/research/venues.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Venues'
+openapi: 'GET /api/research/venues'
+---
diff --git a/api-reference/research/web.mdx b/api-reference/research/web.mdx
new file mode 100644
index 0000000..20373b6
--- /dev/null
+++ b/api-reference/research/web.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Web Search'
+openapi: 'POST /api/research/web'
+---
diff --git a/cli.mdx b/cli.mdx
index 29394ea..bcd1d7b 100644
--- a/cli.mdx
+++ b/cli.mdx
@@ -121,6 +121,327 @@ recoup tasks status --run --json
|------|----------|-------------|
| `--run ` | Yes | Trigger.dev run ID |
+## research
+
+Music industry research — streaming metrics, audience demographics, playlist placements, competitive analysis, and web intelligence. All data is accessed through your `RECOUP_API_KEY`.
+
+Artist-scoped commands (like `metrics`, `audience`, `similar`) accept an **artist name** or a **Recoup artist ID** (UUID). The API resolves the artist automatically. If the name is ambiguous (multiple matches), the API returns the top results for disambiguation.
+
+### Search for an artist
+
+```bash
+recoup research "Drake"
+recoup research "Phoebe Bridgers" --json
+```
+
+### Lookup by platform URL
+
+Find an artist from a Spotify URL, Apple Music link, or any platform ID.
+
+```bash
+recoup research lookup "https://open.spotify.com/artist/3TVXtAsR1Inumwj472S9r4"
+recoup research lookup "3TVXtAsR1Inumwj472S9r4"
+```
+
+See [`GET /api/research/lookup`](/api-reference/research/lookup).
+
+### Artist profile and career
+
+```bash
+recoup research profile "Drake"
+recoup research career "Drake"
+recoup research insights "Drake"
+```
+
+| Subcommand | Description | API endpoint |
+|------------|-------------|-------------|
+| `profile` | Full artist profile — bio, genres, social URLs, label | [`GET /api/research/profile`](/api-reference/research/profile) |
+| `career` | Career timeline and key milestones | [`GET /api/research/career`](/api-reference/research/career) |
+| `insights` | AI-generated observations and trends | [`GET /api/research/insights`](/api-reference/research/insights) |
+
+### Streaming and social metrics
+
+Get platform-specific metrics over time. Supports 14 platforms.
+
+```bash
+recoup research metrics "Drake" --source spotify
+recoup research metrics "Drake" --source instagram
+recoup research metrics "Drake" --source tiktok
+recoup research metrics "Drake" --source youtube_channel
+```
+
+Valid `--source` values: `spotify`, `instagram`, `tiktok`, `twitter`, `facebook`, `youtube_channel`, `youtube_artist`, `soundcloud`, `deezer`, `twitch`, `line`, `melon`, `wikipedia`, `bandsintown`.
+
+See [`GET /api/research/metrics`](/api-reference/research/metrics).
+
+### Audience and geography
+
+```bash
+recoup research audience "Drake"
+recoup research audience "Drake" --platform tiktok
+recoup research audience "Drake" --platform youtube
+recoup research cities "Drake"
+```
+
+| Subcommand | Description | API endpoint |
+|------------|-------------|-------------|
+| `audience` | Age, gender, country breakdown. `--platform`: `instagram` (default), `tiktok`, `youtube` | [`GET /api/research/audience`](/api-reference/research/audience) |
+| `cities` | Top cities by listener concentration | [`GET /api/research/cities`](/api-reference/research/cities) |
+
+### Social URLs
+
+Get all social and streaming links for an artist.
+
+```bash
+recoup research urls "Drake"
+```
+
+See [`GET /api/research/urls`](/api-reference/research/urls).
+
+### Instagram posts
+
+Get an artist's top Instagram posts and reels by engagement.
+
+```bash
+recoup research instagram-posts "Drake"
+```
+
+See [`GET /api/research/instagram-posts`](/api-reference/research/instagram-posts).
+
+### Competitive landscape
+
+```bash
+recoup research similar "Drake"
+recoup research similar "Drake" --audience high --genre high --limit 20
+```
+
+Configuration options: `--audience`, `--genre`, `--mood`, `--musicality` (values: `high`, `medium`, `low`).
+
+See [`GET /api/research/similar`](/api-reference/research/similar).
+
+### Playlists
+
+```bash
+recoup research playlists "Drake"
+recoup research playlists "Drake" --platform applemusic
+recoup research playlists "Drake" --editorial
+recoup research playlists "Drake" --status past --since 2025-01-01
+recoup research playlists "Drake" --sort followers --limit 50
+```
+
+| Flag | Description |
+|------|-------------|
+| `--platform ` | `spotify` (default), `applemusic`, `deezer`, `amazon`, `youtube` |
+| `--editorial` | Only editorial playlists |
+| `--status ` | `current` (default) or `past` |
+| `--since ` | Filter by date (YYYY-MM-DD) |
+| `--sort ` | Sort results (e.g., `followers`) |
+| `--limit ` | Max results |
+
+See [`GET /api/research/playlists`](/api-reference/research/playlists).
+
+### Discography
+
+```bash
+recoup research albums "Drake"
+recoup research tracks "Drake"
+```
+
+### Track details
+
+Get metadata for a specific track — look up by name or Spotify URL.
+
+```bash
+recoup research track "God's Plan"
+recoup research track "https://open.spotify.com/track/2grjqo0Frpf2..."
+```
+
+See [`GET /api/research/track/{id}`](/api-reference/research/track).
+
+### Playlist and curator details
+
+Get metadata for a specific playlist or its curator.
+
+```bash
+recoup research playlist spotify 37i9dQZF1DXcBWIGoYBM5M
+recoup research curator spotify 1
+```
+
+See [`GET /api/research/playlist/{platform}/{id}`](/api-reference/research/playlist) and [`GET /api/research/curator/{platform}/{id}`](/api-reference/research/curator).
+
+### Discover artists
+
+Find artists by criteria — country, genre, listener ranges, growth rate.
+
+```bash
+recoup research discover --country US --spotify-listeners 100000 500000
+recoup research discover --genre 86 --sort weekly_diff.sp_monthly_listeners
+recoup research discover --tiktok-followers 1000000 10000000 --spotify-listeners 0 100000
+```
+
+| Flag | Description |
+|------|-------------|
+| `--country ` | ISO country code (US, BR, GB, etc.) |
+| `--genre ` | Genre ID (use `recoup research genres` to list) |
+| `--spotify-listeners ` | Monthly listener range |
+| `--tiktok-followers ` | TikTok follower range |
+| `--sort ` | Sort field (e.g., `weekly_diff.sp_monthly_listeners`) |
+
+See [`GET /api/research/discover`](/api-reference/research/discover).
+
+### Milestones
+
+Get an artist's activity feed — playlist adds, chart entries, and notable events.
+
+```bash
+recoup research milestones "Drake"
+recoup research milestones "Drake" --json
+```
+
+See [`GET /api/research/milestones`](/api-reference/research/milestones).
+
+### Venues
+
+Get venues an artist has performed at, including capacity and location.
+
+```bash
+recoup research venues "Drake"
+recoup research venues "Drake" --json
+```
+
+See [`GET /api/research/venues`](/api-reference/research/venues).
+
+### Rank
+
+Get an artist's global Chartmetric ranking.
+
+```bash
+recoup research rank "Drake"
+recoup research rank "Drake" --json
+```
+
+See [`GET /api/research/rank`](/api-reference/research/rank).
+
+### Charts
+
+Get global chart positions for a platform. NOT artist-scoped — returns the full chart.
+
+```bash
+recoup research charts --platform spotify
+recoup research charts --platform spotify --country US
+recoup research charts --platform applemusic --country GB --interval weekly --json
+```
+
+| Flag | Required | Description |
+|------|----------|-------------|
+| `--platform ` | Yes | Chart platform (spotify, applemusic, tiktok, youtube, itunes, shazam) |
+| `--country ` | No | ISO country code (US, GB, DE, etc.) |
+| `--interval ` | No | Time interval (e.g. daily, weekly) |
+| `--type ` | No | Chart type (varies by platform) |
+
+See [`GET /api/research/charts`](/api-reference/research/charts).
+
+### Radio stations
+
+List radio stations tracked by Chartmetric.
+
+```bash
+recoup research radio
+recoup research radio --json
+```
+
+See [`GET /api/research/radio`](/api-reference/research/radio).
+
+### Reference data
+
+```bash
+recoup research genres
+recoup research festivals
+```
+
+### Web research
+
+Search the web for narrative context, press coverage, and cultural information that structured data doesn't cover.
+
+```bash
+recoup research web "Drake brand partnerships sync licensing"
+recoup research web "Phoebe Bridgers fan community psychographics"
+```
+
+See [`POST /api/research/web`](/api-reference/research/web).
+
+### Deep research report
+
+Comprehensive multi-source research that synthesizes information from across the web into a cited report.
+
+```bash
+recoup research report "Drake"
+recoup research report "Tell me everything about Phoebe Bridgers — bio, streaming metrics, fan base, competitive landscape, and revenue opportunities"
+```
+
+See [`POST /api/research/deep`](/api-reference/research/deep).
+
+### People search
+
+Search for people in the music industry — artists, managers, A&R reps, producers. Returns profiles with LinkedIn data.
+
+```bash
+recoup research people "A&R reps at Atlantic Records"
+recoup research people "music managers in Los Angeles R&B"
+```
+
+See [`POST /api/research/people`](/api-reference/research/people).
+
+### Extract URL
+
+Extract clean markdown content from any public URL. Handles JavaScript-heavy pages and PDFs.
+
+```bash
+recoup research extract "https://en.wikipedia.org/wiki/Drake_(musician)" --objective "biography and discography"
+recoup research extract "https://open.spotify.com/artist/..." --full-content
+```
+
+Accepts up to 10 URLs per call.
+
+See [`POST /api/research/extract`](/api-reference/research/extract).
+
+### Enrich
+
+Get structured data about any entity from web research. Provide a description and a JSON schema — get typed data back with citations.
+
+```bash
+recoup research enrich "Drake rapper" --schema '{"properties": {"real_name": {"type": "string"}, "label": {"type": "string"}, "hometown": {"type": "string"}}}'
+```
+
+Processors: `base` (fast, default), `core` (balanced), `ultra` (comprehensive).
+
+See [`POST /api/research/enrich`](/api-reference/research/enrich).
+
+### Using Recoup artist IDs
+
+Artist IDs are supported on artist-scoped commands (see the note above). Example:
+
+```bash
+recoup research metrics de05ba8c-7e29-4f1a-93a7-3635653599f6 --source spotify
+```
+
+### Workflow example: full artist research
+
+```bash
+# Pull structured data (all by name, run in parallel)
+recoup research metrics "Phoebe Bridgers" --source spotify --json
+recoup research audience "Phoebe Bridgers" --json
+recoup research cities "Phoebe Bridgers" --json
+recoup research similar "Phoebe Bridgers" --audience high --genre high --json
+recoup research playlists "Phoebe Bridgers" --editorial --json
+
+# Add web context
+recoup research web "Phoebe Bridgers biography career milestones" --json
+recoup research web "Phoebe Bridgers fan community brand partnerships" --json
+```
+
+---
+
## content
Content-creation pipeline commands. Generate AI-powered social videos for artists.
diff --git a/docs.json b/docs.json
index 9a686e2..481cde0 100644
--- a/docs.json
+++ b/docs.json
@@ -147,6 +147,41 @@
"api-reference/workspaces/create"
]
},
+ {
+ "group": "Research",
+ "pages": [
+ "api-reference/research/search",
+ "api-reference/research/lookup",
+ "api-reference/research/profile",
+ "api-reference/research/metrics",
+ "api-reference/research/audience",
+ "api-reference/research/cities",
+ "api-reference/research/similar",
+ "api-reference/research/urls",
+ "api-reference/research/instagram-posts",
+ "api-reference/research/playlists",
+ "api-reference/research/albums",
+ "api-reference/research/tracks",
+ "api-reference/research/track",
+ "api-reference/research/career",
+ "api-reference/research/insights",
+ "api-reference/research/playlist",
+ "api-reference/research/curator",
+ "api-reference/research/discover",
+ "api-reference/research/genres",
+ "api-reference/research/festivals",
+ "api-reference/research/web",
+ "api-reference/research/deep",
+ "api-reference/research/people",
+ "api-reference/research/extract",
+ "api-reference/research/enrich",
+ "api-reference/research/milestones",
+ "api-reference/research/venues",
+ "api-reference/research/rank",
+ "api-reference/research/charts",
+ "api-reference/research/radio"
+ ]
+ },
{
"group": "Spotify",
"pages": [