From 322e39654ecc7de39089f37a3c62baafea10b0d5 Mon Sep 17 00:00:00 2001 From: Recoup CTO Agent Date: Mon, 6 Apr 2026 02:52:37 +0000 Subject: [PATCH 1/6] docs: add Agent Signup and Verify endpoint documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add two new unauthenticated endpoints for programmatic agent onboarding: - POST /api/agents/signup — register with email, instant key for agent+ prefix - POST /api/agents/verify — verify email with 6-digit code to get API key Changes: - openapi.json: new paths + 4 component schemas - api-reference/agents/signup.mdx and verify.mdx (frontmatter-only) - docs.json: Agent Onboarding group in Accounts tab - quickstart.mdx: Agent Onboarding section with curl examples - index.mdx: Agent Signup card + LLM reference line - authentication.mdx: Agent Onboarding section Co-Authored-By: Paperclip --- api-reference/agents/signup.mdx | 4 + api-reference/agents/verify.mdx | 4 + api-reference/openapi.json | 298 +++++++++++++++++++++++++------- authentication.mdx | 15 ++ docs.json | 7 + index.mdx | 8 + quickstart.mdx | 35 ++++ 7 files changed, 304 insertions(+), 67 deletions(-) create mode 100644 api-reference/agents/signup.mdx create mode 100644 api-reference/agents/verify.mdx diff --git a/api-reference/agents/signup.mdx b/api-reference/agents/signup.mdx new file mode 100644 index 0000000..3918286 --- /dev/null +++ b/api-reference/agents/signup.mdx @@ -0,0 +1,4 @@ +--- +title: 'Agent Signup' +openapi: 'POST /api/agents/signup' +--- diff --git a/api-reference/agents/verify.mdx b/api-reference/agents/verify.mdx new file mode 100644 index 0000000..e1e082f --- /dev/null +++ b/api-reference/agents/verify.mdx @@ -0,0 +1,4 @@ +--- +title: 'Verify Agent Email' +openapi: 'POST /api/agents/verify' +--- diff --git a/api-reference/openapi.json b/api-reference/openapi.json index ac64a21..b9c3622 100644 --- a/api-reference/openapi.json +++ b/api-reference/openapi.json @@ -2821,7 +2821,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 \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.", + "description": "Upload one or more files to the authenticated account's sandbox GitHub repository. Accepts an array of file URLs and commits each file to the specified directory path within the repository. Supports submodule resolution — if the target path falls within a git submodule, the file is committed to the submodule's repository. Authentication is handled via the x-api-key header or Authorization Bearer token.", "requestBody": { "description": "JSON body containing file URLs and target path", "required": true, @@ -4043,7 +4043,7 @@ }, "/api/content/create": { "post": { - "description": "Trigger the content creation pipeline for an artist. Provide `artist_account_id` to identify the target artist. Validates the artist has all required files (face guide, songs) unless overridden via `songs` URLs or `images`, then triggers a background task that generates a short-form video. Returns `runIds` \u2014 an array of run IDs that can each be polled via [GET /api/tasks/runs](/api-reference/tasks/runs).", + "description": "Trigger the content creation pipeline for an artist. Provide `artist_account_id` to identify the target artist. Validates the artist has all required files (face guide, songs) unless overridden via `songs` URLs or `images`, then triggers a background task that generates a short-form video. Returns `runIds` — an array of run IDs that can each be polled via [GET /api/tasks/runs](/api-reference/tasks/runs).", "security": [ { "apiKeyAuth": [] @@ -4065,7 +4065,7 @@ }, "responses": { "202": { - "description": "Pipeline triggered successfully. Returns `runIds` \u2014 an array of run IDs. Poll each via [GET /api/tasks/runs](/api-reference/tasks/runs) to check progress.", + "description": "Pipeline triggered successfully. Returns `runIds` — an array of run IDs. Poll each via [GET /api/tasks/runs](/api-reference/tasks/runs) to check progress.", "content": { "application/json": { "schema": { @@ -4075,7 +4075,7 @@ } }, "400": { - "description": "Validation failed \u2014 missing artist identifier, artist is missing required files, or template not found", + "description": "Validation failed — missing artist identifier, artist is missing required files, or template not found", "content": { "application/json": { "schema": { @@ -4085,7 +4085,7 @@ } }, "401": { - "description": "Unauthorized \u2014 invalid or missing API key", + "description": "Unauthorized — invalid or missing API key", "content": { "application/json": { "schema": { @@ -4095,7 +4095,7 @@ } }, "404": { - "description": "Artist not found \u2014 the provided artist_account_id does not match any artist", + "description": "Artist not found — the provided artist_account_id does not match any artist", "content": { "application/json": { "schema": { @@ -4130,7 +4130,7 @@ } }, "401": { - "description": "Unauthorized \u2014 invalid or missing API key", + "description": "Unauthorized — invalid or missing API key", "content": { "application/json": { "schema": { @@ -4178,7 +4178,7 @@ } }, "400": { - "description": "Bad request \u2014 artist_account_id is required", + "description": "Bad request — artist_account_id is required", "content": { "application/json": { "schema": { @@ -4188,7 +4188,7 @@ } }, "401": { - "description": "Unauthorized \u2014 invalid or missing API key", + "description": "Unauthorized — invalid or missing API key", "content": { "application/json": { "schema": { @@ -4198,7 +4198,7 @@ } }, "404": { - "description": "Artist not found \u2014 the provided artist_account_id does not match any artist", + "description": "Artist not found — the provided artist_account_id does not match any artist", "content": { "application/json": { "schema": { @@ -4212,7 +4212,7 @@ }, "/api/content/estimate": { "get": { - "description": "Estimate the cost of running the content creation pipeline. Calculates per-step and per-video costs based on current pricing. Supports comparing multiple workflow profiles (e.g., premium vs. budget) and projecting batch costs. This endpoint is informational only \u2014 it does not trigger any pipeline execution or spend credits.", + "description": "Estimate the cost of running the content creation pipeline. Calculates per-step and per-video costs based on current pricing. Supports comparing multiple workflow profiles (e.g., premium vs. budget) and projecting batch costs. This endpoint is informational only — it does not trigger any pipeline execution or spend credits.", "security": [ { "apiKeyAuth": [] @@ -4268,7 +4268,7 @@ } }, "401": { - "description": "Unauthorized \u2014 invalid or missing API key", + "description": "Unauthorized — invalid or missing API key", "content": { "application/json": { "schema": { @@ -4343,7 +4343,7 @@ } }, "401": { - "description": "Unauthorized \u2014 invalid or missing API key / Bearer token", + "description": "Unauthorized — invalid or missing API key / Bearer token", "content": { "application/json": { "schema": { @@ -4357,7 +4357,7 @@ }, "/api/songs/analyze": { "post": { - "description": "Analyze music using a state-of-the-art Audio Language Model that listens directly to the audio waveform. Unlike text-based AI, this model processes the actual sound \u2014 identifying harmony, structure, timbre, lyrics, and cultural context through deep music understanding. Supports audio up to 20 minutes (MP3, WAV, FLAC). Two modes: (1) **Presets** \u2014 pass a `preset` name like `catalog_metadata`, `mood_tags`, or `full_report` for structured, optimized output. (2) **Custom prompt** \u2014 pass a `prompt` for free-form questions. The `full_report` preset runs all 13 presets in parallel and returns a comprehensive music intelligence report. Use `GET /api/songs/analyze/presets` to list available presets.", + "description": "Analyze music using a state-of-the-art Audio Language Model that listens directly to the audio waveform. Unlike text-based AI, this model processes the actual sound — identifying harmony, structure, timbre, lyrics, and cultural context through deep music understanding. Supports audio up to 20 minutes (MP3, WAV, FLAC). Two modes: (1) **Presets** — pass a `preset` name like `catalog_metadata`, `mood_tags`, or `full_report` for structured, optimized output. (2) **Custom prompt** — pass a `prompt` for free-form questions. The `full_report` preset runs all 13 presets in parallel and returns a comprehensive music intelligence report. Use `GET /api/songs/analyze/presets` to list available presets.", "security": [ { "apiKeyAuth": [] @@ -4389,7 +4389,7 @@ } }, "400": { - "description": "Bad request \u2014 missing or invalid fields", + "description": "Bad request — missing or invalid fields", "content": { "application/json": { "schema": { @@ -4399,7 +4399,7 @@ } }, "401": { - "description": "Unauthorized \u2014 invalid or missing API key / Bearer token", + "description": "Unauthorized — invalid or missing API key / Bearer token", "content": { "application/json": { "schema": { @@ -4409,7 +4409,7 @@ } }, "500": { - "description": "Server error \u2014 upstream model unavailable or inference failed", + "description": "Server error — upstream model unavailable or inference failed", "content": { "application/json": { "schema": { @@ -4481,7 +4481,7 @@ }, "/api/admins": { "get": { - "description": "Check if the authenticated account is a Recoup admin. An account is considered an admin if it is a member of the Recoup organization. No input parameters required \u2014 authentication is performed via the x-api-key or Authorization header.", + "description": "Check if the authenticated account is a Recoup admin. An account is considered an admin if it is a member of the Recoup organization. No input parameters required — authentication is performed via the x-api-key or Authorization header.", "parameters": [], "security": [ { @@ -5318,7 +5318,7 @@ "application/json": { "schema": { "type": "object", - "description": "Slack Events API envelope \u2014 the shape depends on the event type" + "description": "Slack Events API envelope — the shape depends on the event type" } } } @@ -5348,7 +5348,7 @@ }, "/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 \u2014 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 — 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, @@ -5485,7 +5485,7 @@ } }, "400": { - "description": "Validation failed \u2014 invalid or missing request body fields", + "description": "Validation failed — invalid or missing request body fields", "content": { "application/json": { "schema": { @@ -5495,7 +5495,7 @@ } }, "401": { - "description": "Unauthorized \u2014 invalid or missing API key", + "description": "Unauthorized — invalid or missing API key", "content": { "application/json": { "schema": { @@ -5519,7 +5519,7 @@ }, "/api/content/analyze": { "post": { - "description": "Analyze a video and answer questions about it. Pass a video URL and a text prompt \u2014 for example, \"Describe what happens\" or \"Rate the visual quality 1-10.\" Returns the generated text.", + "description": "Analyze a video and answer questions about it. Pass a video URL and a text prompt — for example, \"Describe what happens\" or \"Rate the visual quality 1-10.\" Returns the generated text.", "security": [ { "apiKeyAuth": [] @@ -5551,7 +5551,7 @@ } }, "400": { - "description": "Validation failed \u2014 invalid or missing request body fields", + "description": "Validation failed — invalid or missing request body fields", "content": { "application/json": { "schema": { @@ -5561,7 +5561,7 @@ } }, "401": { - "description": "Unauthorized \u2014 invalid or missing API key", + "description": "Unauthorized — invalid or missing API key", "content": { "application/json": { "schema": { @@ -5617,7 +5617,7 @@ } }, "400": { - "description": "Validation failed \u2014 invalid or missing request body fields", + "description": "Validation failed — invalid or missing request body fields", "content": { "application/json": { "schema": { @@ -5627,7 +5627,7 @@ } }, "401": { - "description": "Unauthorized \u2014 invalid or missing API key", + "description": "Unauthorized — invalid or missing API key", "content": { "application/json": { "schema": { @@ -5683,7 +5683,7 @@ } }, "400": { - "description": "Validation failed \u2014 invalid or missing request body fields", + "description": "Validation failed — invalid or missing request body fields", "content": { "application/json": { "schema": { @@ -5693,7 +5693,7 @@ } }, "401": { - "description": "Unauthorized \u2014 invalid or missing API key", + "description": "Unauthorized — invalid or missing API key", "content": { "application/json": { "schema": { @@ -5717,7 +5717,7 @@ }, "/api/content/video": { "post": { - "description": "Generate a video. Set `mode` to control what kind of video you get:\n\n- `prompt` \u2014 create a video from a text description\n- `animate` \u2014 animate a still image\n- `reference` \u2014 use an image as a style/subject reference (not the first frame)\n- `extend` \u2014 continue an existing video\n- `first-last` \u2014 generate a video that transitions between two images\n- `lipsync` \u2014 sync face movement to an audio clip\n\nIf `mode` is omitted, it's inferred from the inputs you provide.", + "description": "Generate a video. Set `mode` to control what kind of video you get:\n\n- `prompt` — create a video from a text description\n- `animate` — animate a still image\n- `reference` — use an image as a style/subject reference (not the first frame)\n- `extend` — continue an existing video\n- `first-last` — generate a video that transitions between two images\n- `lipsync` — sync face movement to an audio clip\n\nIf `mode` is omitted, it's inferred from the inputs you provide.", "security": [ { "apiKeyAuth": [] @@ -5749,7 +5749,7 @@ } }, "400": { - "description": "Validation failed \u2014 invalid or missing request body fields", + "description": "Validation failed — invalid or missing request body fields", "content": { "application/json": { "schema": { @@ -5759,7 +5759,7 @@ } }, "401": { - "description": "Unauthorized \u2014 invalid or missing API key", + "description": "Unauthorized — invalid or missing API key", "content": { "application/json": { "schema": { @@ -5781,7 +5781,7 @@ } }, "patch": { - "description": "Apply edits to a video or audio file \u2014 trim, crop, resize, overlay text, or add an audio track. Pass a `template` for a preset edit pipeline, or build your own with an `operations` array. Everything runs in one pass.", + "description": "Apply edits to a video or audio file — trim, crop, resize, overlay text, or add an audio track. Pass a `template` for a preset edit pipeline, or build your own with an `operations` array. Everything runs in one pass.", "security": [ { "apiKeyAuth": [] @@ -5813,7 +5813,7 @@ } }, "400": { - "description": "Validation failed \u2014 invalid or missing request body fields", + "description": "Validation failed — invalid or missing request body fields", "content": { "application/json": { "schema": { @@ -5823,7 +5823,7 @@ } }, "401": { - "description": "Unauthorized \u2014 invalid or missing API key", + "description": "Unauthorized — invalid or missing API key", "content": { "application/json": { "schema": { @@ -5879,7 +5879,7 @@ } }, "400": { - "description": "Validation failed \u2014 invalid or missing request body fields", + "description": "Validation failed — invalid or missing request body fields", "content": { "application/json": { "schema": { @@ -5889,7 +5889,7 @@ } }, "401": { - "description": "Unauthorized \u2014 invalid or missing API key", + "description": "Unauthorized — invalid or missing API key", "content": { "application/json": { "schema": { @@ -5969,7 +5969,7 @@ }, "/api/research/albums": { "get": { - "description": "Get an artist's full discography \u2014 albums, EPs, and singles with release dates.", + "description": "Get an artist's full discography — albums, EPs, and singles with release dates.", "parameters": [ { "name": "artist", @@ -5997,7 +5997,7 @@ }, "/api/research/audience": { "get": { - "description": "Get audience demographics for an artist on a specific platform \u2014 age, gender, and country breakdown.", + "description": "Get audience demographics for an artist on a specific platform — age, gender, and country breakdown.", "parameters": [ { "name": "artist", @@ -6040,7 +6040,7 @@ }, "/api/research/career": { "get": { - "description": "Get an artist's career timeline \u2014 key milestones, trajectory, and career stage.", + "description": "Get an artist's career timeline — key milestones, trajectory, and career stage.", "parameters": [ { "name": "artist", @@ -6068,7 +6068,7 @@ }, "/api/research/charts": { "get": { - "description": "Get global chart positions for a platform \u2014 Spotify, Apple Music, TikTok, YouTube, iTunes, Shazam, etc. NOT artist-scoped. Returns ranked entries with track and artist info.", + "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", @@ -6161,7 +6161,7 @@ }, "/api/research/curator": { "get": { - "description": "Get curator profile \u2014 who curates a playlist, their other playlists, and follower reach.", + "description": "Get curator profile — who curates a playlist, their other playlists, and follower reach.", "parameters": [ { "name": "platform", @@ -6232,7 +6232,7 @@ }, "/api/research/discover": { "get": { - "description": "Discover artists by criteria \u2014 filter by country, genre, Spotify monthly listener range, and sort by growth metrics.", + "description": "Discover artists by criteria — filter by country, genre, Spotify monthly listener range, and sort by growth metrics.", "parameters": [ { "name": "country", @@ -6391,7 +6391,7 @@ }, "/api/research/insights": { "get": { - "description": "Get AI-generated insights about an artist \u2014 automatically surfaced trends, milestones, and observations.", + "description": "Get AI-generated insights about an artist — automatically surfaced trends, milestones, and observations.", "parameters": [ { "name": "artist", @@ -6447,7 +6447,7 @@ }, "/api/research/lookup": { "get": { - "description": "Look up an artist by a platform URL or ID \u2014 Spotify URL, Spotify ID, Apple Music URL, etc.", + "description": "Look up an artist by a platform URL or ID — Spotify URL, Spotify ID, Apple Music URL, etc.", "parameters": [ { "name": "url", @@ -6475,7 +6475,7 @@ }, "/api/research/metrics": { "get": { - "description": "Get platform-specific metrics for an artist over time \u2014 followers, listeners, views, engagement. Supports 14 platforms.", + "description": "Get platform-specific metrics for an artist over time — followers, listeners, views, engagement. Supports 14 platforms.", "parameters": [ { "name": "artist", @@ -6528,7 +6528,7 @@ }, "/api/research/milestones": { "get": { - "description": "Get an artist's activity feed \u2014 playlist adds, chart entries, and other notable events. Each milestone includes a date, summary, platform, track name, and star rating.", + "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", @@ -6556,7 +6556,7 @@ }, "/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.", + "description": "Search for people in the music industry — artists, managers, A&R reps, producers. Returns multi-source profiles including LinkedIn data.", "requestBody": { "required": true, "content": { @@ -6583,7 +6583,7 @@ }, "/api/research/playlist": { "get": { - "description": "Get playlist metadata \u2014 name, description, follower count, track count, and curator info.", + "description": "Get playlist metadata — name, description, follower count, track count, and curator info.", "parameters": [ { "name": "platform", @@ -6627,7 +6627,7 @@ }, "/api/research/playlists": { "get": { - "description": "Get an artist's playlist placements \u2014 editorial, algorithmic, and indie playlists across platforms.", + "description": "Get an artist's playlist placements — editorial, algorithmic, and indie playlists across platforms.", "parameters": [ { "name": "artist", @@ -6721,7 +6721,7 @@ }, "/api/research/profile": { "get": { - "description": "Get a full artist profile \u2014 bio, genres, social URLs, label, career stage, and basic metrics.", + "description": "Get a full artist profile — bio, genres, social URLs, label, career stage, and basic metrics.", "parameters": [ { "name": "artist", @@ -6887,7 +6887,7 @@ }, "/api/research/track": { "get": { - "description": "Get track metadata \u2014 title, artist, album, release date, popularity, and platform IDs.", + "description": "Get track metadata — title, artist, album, release date, popularity, and platform IDs.", "parameters": [ { "name": "q", @@ -6943,7 +6943,7 @@ }, "/api/research/urls": { "get": { - "description": "Get all social and streaming URLs for an artist \u2014 Spotify, Instagram, TikTok, YouTube, Twitter, SoundCloud, and more.", + "description": "Get all social and streaming URLs for an artist — Spotify, Instagram, TikTok, YouTube, Twitter, SoundCloud, and more.", "parameters": [ { "name": "artist", @@ -7023,6 +7023,84 @@ } } } + }, + "/api/agents/signup": { + "post": { + "description": "Register an agent. For new agent+ emails, returns an API key immediately. For all other cases, sends a verification code to the email — call /api/agents/verify with the code to get your API key.", + "security": [], + "requestBody": { + "description": "Agent email to register", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AgentSignupRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Signup processed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AgentSignupResponse" + } + } + } + } + } + } + }, + "/api/agents/verify": { + "post": { + "description": "Verify an agent's email with the code sent during signup. Returns an API key on success.", + "security": [], + "requestBody": { + "description": "Email and verification code", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AgentVerifyRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Verification successful", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AgentVerifyResponse" + } + } + } + }, + "400": { + "description": "Invalid or expired verification code", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "429": { + "description": "Too many failed verification attempts", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } } }, "components": { @@ -12907,7 +12985,7 @@ "items": { "type": "string" }, - "description": "Optional list of song slugs or public URLs to use for the audio track. Song slugs match filenames without extension from the artist's `songs/` directory (e.g. `\"hiccups\"` for `hiccups.mp3`). Public URLs (e.g. `\"https://example.com/my-song.mp3\"`) are downloaded, transcribed, and clipped directly \u2014 bypassing the Git repo. When omitted, all songs in the artist's repo are eligible.", + "description": "Optional list of song slugs or public URLs to use for the audio track. Song slugs match filenames without extension from the artist's `songs/` directory (e.g. `\"hiccups\"` for `hiccups.mp3`). Public URLs (e.g. `\"https://example.com/my-song.mp3\"`) are downloaded, transcribed, and clipped directly — bypassing the Git repo. When omitted, all songs in the artist's repo are eligible.", "example": [ "hiccups", "https://example.com/unreleased-track.mp3" @@ -12937,7 +13015,7 @@ "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.", + "description": "Confirmation that the content creation pipeline has been triggered. Always returns `runIds` as an array — even for a single run, it contains one element.", "properties": { "runIds": { "type": "array", @@ -13416,7 +13494,7 @@ "audio_url": { "type": "string", "format": "uri", - "description": "Public URL to an audio file (MP3, WAV, or FLAC \u2014 up to 20 minutes)", + "description": "Public URL to an audio file (MP3, WAV, or FLAC — up to 20 minutes)", "example": "https://example.com/song.mp3" }, "max_new_tokens": { @@ -13432,7 +13510,7 @@ "minimum": 0, "maximum": 2, "default": 1, - "description": "Controls output creativity \u2014 higher values produce more varied responses", + "description": "Controls output creativity — higher values produce more varied responses", "example": 0.7 }, "top_p": { @@ -14356,7 +14434,7 @@ }, "ResearchAudienceResponse": { "type": "object", - "description": "Audience demographics breakdown \u2014 age ranges, gender split, and country distribution for the specified platform.", + "description": "Audience demographics breakdown — age ranges, gender split, and country distribution for the specified platform.", "properties": { "status": { "type": "string" @@ -14387,7 +14465,7 @@ }, "ResearchCareerResponse": { "type": "object", - "description": "Career timeline \u2014 milestones, trajectory, and career stage history.", + "description": "Career timeline — milestones, trajectory, and career stage history.", "properties": { "status": { "type": "string" @@ -14419,7 +14497,7 @@ }, "data": { "type": "object", - "description": "Chart data \u2014 structure varies by platform.", + "description": "Chart data — structure varies by platform.", "additionalProperties": true } } @@ -14501,7 +14579,7 @@ "properties": { "query": { "type": "string", - "description": "The research question \u2014 be specific and detailed for best results." + "description": "The research question — be specific and detailed for best results." } } }, @@ -14880,7 +14958,7 @@ }, "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.).", + "description": "Time-series metrics for a specific platform. Shape varies by source — typically an array of data points with timestamps and values (followers, listeners, views, etc.).", "properties": { "status": { "type": "string" @@ -15043,7 +15121,7 @@ }, "ResearchPlaylistResponse": { "type": "object", - "description": "Playlist metadata \u2014 name, description, follower count, track count, and curator info.", + "description": "Playlist metadata — name, description, follower count, track count, and curator info.", "properties": { "status": { "type": "string" @@ -15089,7 +15167,7 @@ }, "ResearchProfileResponse": { "type": "object", - "description": "Full artist profile \u2014 bio, genres, social links, label, images, and basic stats.", + "description": "Full artist profile — bio, genres, social links, label, images, and basic stats.", "properties": { "status": { "type": "string" @@ -15281,7 +15359,7 @@ }, "ResearchTrackResponse": { "type": "object", - "description": "Track metadata \u2014 title, artist, album, release date, popularity, and platform IDs.", + "description": "Track metadata — title, artist, album, release date, popularity, and platform IDs.", "properties": { "status": { "type": "string" @@ -15414,7 +15492,7 @@ "properties": { "query": { "type": "string", - "description": "The search query \u2014 what you want to find on the web." + "description": "The search query — what you want to find on the web." }, "max_results": { "type": "integer", @@ -15465,6 +15543,92 @@ "description": "Results formatted as markdown for easy reading." } } + }, + "AgentSignupRequest": { + "type": "object", + "required": [ + "email" + ], + "properties": { + "email": { + "type": "string", + "format": "email", + "description": "The agent email address. Emails with the agent+ prefix (e.g. agent+mybot@example.com) get an API key immediately on first signup.", + "example": "agent+mybot@example.com" + } + } + }, + "AgentSignupResponse": { + "type": "object", + "required": [ + "account_id", + "message" + ], + "properties": { + "account_id": { + "type": "string", + "description": "The account ID for the registered agent.", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "api_key": { + "type": [ + "string", + "null" + ], + "description": "API key returned immediately for new agent+ prefix emails. Null for all other cases — check your email for a verification code.", + "example": "recoup_sk_abc123..." + }, + "message": { + "type": "string", + "description": "Human-readable status message.", + "example": "If this is a new agent+ email, your API key is included. Otherwise, check your email for a verification code." + } + } + }, + "AgentVerifyRequest": { + "type": "object", + "required": [ + "email", + "code" + ], + "properties": { + "email": { + "type": "string", + "format": "email", + "description": "The email address used during signup.", + "example": "you@example.com" + }, + "code": { + "type": "string", + "description": "The 6-digit verification code sent to the email.", + "example": "123456" + } + } + }, + "AgentVerifyResponse": { + "type": "object", + "required": [ + "account_id", + "api_key", + "message" + ], + "properties": { + "account_id": { + "type": "string", + "description": "The account ID for the verified agent.", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "api_key": { + "type": "string", + "description": "API key for the verified account.", + "example": "recoup_sk_abc123..." + }, + "message": { + "type": "string", + "description": "Human-readable status message.", + "example": "Verified" + } + } } }, "securitySchemes": { @@ -15486,4 +15650,4 @@ } } } -} \ No newline at end of file +} diff --git a/authentication.mdx b/authentication.mdx index c25d42f..ea26ba8 100644 --- a/authentication.mdx +++ b/authentication.mdx @@ -104,6 +104,21 @@ Some endpoints accept an `organization_id` parameter. When provided, the API add --- +## Agent Onboarding + +Two unauthenticated endpoints allow agents to create accounts and obtain API keys programmatically: + +- **`POST /api/agents/signup`** — Register with an email address. Emails with the `agent+` prefix (e.g. `agent+mybot@example.com`) receive an API key immediately on first signup. All other cases receive a 6-digit verification code via email. +- **`POST /api/agents/verify`** — Submit the verification code to receive an API key. + +Multiple API keys per account are supported — each signup or verification generates a new key without revoking existing ones. + + +See the [Agent Signup](/api-reference/agents/signup) and [Verify](/api-reference/agents/verify) API reference for request/response details. + + +--- + ## Security Notes - API keys are **never stored in plaintext** — only an HMAC-SHA256 hash (keyed with your project secret) is persisted in the database diff --git a/docs.json b/docs.json index 7fa83a6..61821ad 100644 --- a/docs.json +++ b/docs.json @@ -249,6 +249,13 @@ { "tab": "Accounts", "groups": [ + { + "group": "Agent Onboarding", + "pages": [ + "api-reference/agents/signup", + "api-reference/agents/verify" + ] + }, { "group": "Pulses", "pages": [ diff --git a/index.mdx b/index.mdx index 8290ccb..ba26e4e 100644 --- a/index.mdx +++ b/index.mdx @@ -124,6 +124,13 @@ The API is organized into six main sections. Use these links to jump to the righ > Content creation agent accessible via Slack. Generates images, videos, and captions for artists automatically. + + Programmatic account creation. Get an API key with just an email address. + +See the full [Agent Signup](/api-reference/agents/signup) and [Verify](/api-reference/agents/verify) API reference for details. + + ## API Keys To access the Recoup API programmatically, you'll need to create an API key. From fed5aa1856c01e252227dc122dbfaff53ed7a7da Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Sat, 11 Apr 2026 17:49:50 -0500 Subject: [PATCH 2/6] docs: address PR #104 review feedback - Move Agent Onboarding section from authentication.mdx to new agents.mdx guide (per @sweetmantech), surface it in the Agents nav group - Add the agent+{todaysDate}@recoupable.com tip to the signup endpoint description and agents.mdx - Note the agent onboarding exception in authentication.mdx overview and index.mdx auth section so the "all requests must be auth'd" rule is internally consistent - Constrain AgentVerifyRequest.code to a 6-digit numeric pattern - Mark account_id as format: uuid in AgentSignupResponse and AgentVerifyResponse Co-Authored-By: Claude Opus 4.6 (1M context) --- agents.mdx | 67 +++++++++++++++++++++++++++++ api-reference/openapi/accounts.json | 7 ++- authentication.mdx | 19 ++------ docs.json | 1 + index.mdx | 2 +- 5 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 agents.mdx diff --git a/agents.mdx b/agents.mdx new file mode 100644 index 0000000..e396afb --- /dev/null +++ b/agents.mdx @@ -0,0 +1,67 @@ +--- +title: 'Agents' +description: 'Programmatic agent onboarding — sign up and obtain API keys without human intervention.' +--- + +## Overview + +Two unauthenticated endpoints let agents create accounts and obtain API keys programmatically — no UI, no human in the loop. + +- **[`POST /api/agents/signup`](/api-reference/agents/signup)** — Register with an email address. Emails with the `agent+` prefix (e.g. `agent+mybot@example.com`) receive an API key immediately on first signup. All other cases receive a 6-digit verification code via email. +- **[`POST /api/agents/verify`](/api-reference/agents/verify)** — Submit the verification code to receive an API key. + +Multiple API keys per account are supported — each signup or verification generates a new key without revoking existing ones. + + +If you're unsure what email to register, use `agent+{todaysDate}@recoupable.com` (e.g. `agent+2026-04-11@recoupable.com`). This guarantees the `agent+` prefix path — you'll receive an API key instantly on the first response without needing email verification. + + +## Instant Signup (agent+ prefix) + +```bash +curl -X POST "https://recoup-api.vercel.app/api/agents/signup" \ + -H "Content-Type: application/json" \ + -d '{"email": "agent+mybot@example.com"}' +``` + +Response: + +```json +{ + "account_id": "123e4567-e89b-12d3-a456-426614174000", + "api_key": "recoup_sk_abc123...", + "message": "If this is a new agent+ email, your API key is included. Otherwise, check your email for a verification code." +} +``` + +## Standard Signup (email verification) + +Step 1 — request a verification code: + +```bash +curl -X POST "https://recoup-api.vercel.app/api/agents/signup" \ + -H "Content-Type: application/json" \ + -d '{"email": "you@example.com"}' +``` + +Step 2 — submit the code from the verification email: + +```bash +curl -X POST "https://recoup-api.vercel.app/api/agents/verify" \ + -H "Content-Type: application/json" \ + -d '{"email": "you@example.com", "code": "123456"}' +``` + +Response: + +```json +{ + "account_id": "123e4567-e89b-12d3-a456-426614174000", + "api_key": "recoup_sk_abc123...", + "message": "Verified" +} +``` + +## Next Steps + +Once you have an API key, see [Authentication](/authentication) for how to use it, and [Quickstart](/quickstart) for your first API call. diff --git a/api-reference/openapi/accounts.json b/api-reference/openapi/accounts.json index 8c3a043..c25ec18 100644 --- a/api-reference/openapi/accounts.json +++ b/api-reference/openapi/accounts.json @@ -1466,7 +1466,7 @@ }, "/api/agents/signup": { "post": { - "description": "Register an agent. For new agent+ emails, returns an API key immediately. For all other cases, sends a verification code to the email — call /api/agents/verify with the code to get your API key.", + "description": "Register an agent. For new agent+ emails, returns an API key immediately. For all other cases, sends a verification code to the email — call /api/agents/verify with the code to get your API key.\n\n**Tip:** If you're unsure what email to register, use `agent+{todaysDate}@recoupable.com` (e.g. `agent+2026-04-11@recoupable.com`). This guarantees the `agent+` prefix path and returns an API key instantly — no email verification needed.", "security": [], "requestBody": { "description": "Agent email to register", @@ -2751,6 +2751,7 @@ "properties": { "account_id": { "type": "string", + "format": "uuid", "description": "The account ID for the registered agent.", "example": "123e4567-e89b-12d3-a456-426614174000" }, @@ -2784,6 +2785,9 @@ }, "code": { "type": "string", + "minLength": 6, + "maxLength": 6, + "pattern": "^[0-9]{6}$", "description": "The 6-digit verification code sent to the email.", "example": "123456" } @@ -2799,6 +2803,7 @@ "properties": { "account_id": { "type": "string", + "format": "uuid", "description": "The account ID for the verified agent.", "example": "123e4567-e89b-12d3-a456-426614174000" }, diff --git a/authentication.mdx b/authentication.mdx index ea26ba8..e7b7850 100644 --- a/authentication.mdx +++ b/authentication.mdx @@ -14,6 +14,10 @@ Every request to the Recoup API must be authenticated using exactly one of two m Providing both headers in the same request will result in a `401` error. + +Agent onboarding endpoints (`POST /api/agents/signup` and `POST /api/agents/verify`) are **unauthenticated** — they exist so agents can obtain their first API key. See the [Agents guide](/agents) for details. + + --- ## API Keys @@ -104,21 +108,6 @@ Some endpoints accept an `organization_id` parameter. When provided, the API add --- -## Agent Onboarding - -Two unauthenticated endpoints allow agents to create accounts and obtain API keys programmatically: - -- **`POST /api/agents/signup`** — Register with an email address. Emails with the `agent+` prefix (e.g. `agent+mybot@example.com`) receive an API key immediately on first signup. All other cases receive a 6-digit verification code via email. -- **`POST /api/agents/verify`** — Submit the verification code to receive an API key. - -Multiple API keys per account are supported — each signup or verification generates a new key without revoking existing ones. - - -See the [Agent Signup](/api-reference/agents/signup) and [Verify](/api-reference/agents/verify) API reference for request/response details. - - ---- - ## Security Notes - API keys are **never stored in plaintext** — only an HMAC-SHA256 hash (keyed with your project secret) is persisted in the database diff --git a/docs.json b/docs.json index 9eea57e..a78bcd0 100644 --- a/docs.json +++ b/docs.json @@ -26,6 +26,7 @@ { "group": "Agents", "pages": [ + "agents", "content-agent" ] } diff --git a/index.mdx b/index.mdx index ba26e4e..6fd2575 100644 --- a/index.mdx +++ b/index.mdx @@ -23,7 +23,7 @@ https://recoup-api.vercel.app/api ## Authentication -All API endpoints are authenticated using an API key passed in the `x-api-key` header. +Most API endpoints are authenticated using an API key passed in the `x-api-key` header. The only exceptions are the [agent onboarding](/agents) endpoints (`POST /api/agents/signup` and `POST /api/agents/verify`), which are intentionally unauthenticated so agents can obtain their first API key. 1. Navigate to the [API Keys Management Page](https://chat.recoupable.com/keys) 2. Sign in with your account From c9a8e724a7bac2d45b26cdb81327e75e2de2a6bb Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Sat, 11 Apr 2026 17:56:55 -0500 Subject: [PATCH 3/6] docs: follow-up review fixes for agent onboarding - Link /api/agents/verify in the signup endpoint description - Switch the easy-email tip to agent+{Date.now()}@recoupable.com so agents signing up within the same second still get unique addresses (applied in agents.mdx and the OpenAPI description) - Hyperlink both /api/agents/signup and /api/agents/verify in the index.mdx authentication section Co-Authored-By: Claude Opus 4.6 (1M context) --- agents.mdx | 2 +- api-reference/openapi/accounts.json | 2 +- index.mdx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/agents.mdx b/agents.mdx index e396afb..394a986 100644 --- a/agents.mdx +++ b/agents.mdx @@ -13,7 +13,7 @@ Two unauthenticated endpoints let agents create accounts and obtain API keys pro Multiple API keys per account are supported — each signup or verification generates a new key without revoking existing ones. -If you're unsure what email to register, use `agent+{todaysDate}@recoupable.com` (e.g. `agent+2026-04-11@recoupable.com`). This guarantees the `agent+` prefix path — you'll receive an API key instantly on the first response without needing email verification. +If you're unsure what email to register, use `agent+{Date.now()}@recoupable.com` — the current Unix timestamp in milliseconds (e.g. `agent+1744410896789@recoupable.com`). This guarantees a unique `agent+` address even if you sign up multiple agents within the same second, and returns an API key instantly without needing email verification. ## Instant Signup (agent+ prefix) diff --git a/api-reference/openapi/accounts.json b/api-reference/openapi/accounts.json index c25ec18..6e84d0e 100644 --- a/api-reference/openapi/accounts.json +++ b/api-reference/openapi/accounts.json @@ -1466,7 +1466,7 @@ }, "/api/agents/signup": { "post": { - "description": "Register an agent. For new agent+ emails, returns an API key immediately. For all other cases, sends a verification code to the email — call /api/agents/verify with the code to get your API key.\n\n**Tip:** If you're unsure what email to register, use `agent+{todaysDate}@recoupable.com` (e.g. `agent+2026-04-11@recoupable.com`). This guarantees the `agent+` prefix path and returns an API key instantly — no email verification needed.", + "description": "Register an agent. For new agent+ emails, returns an API key immediately. For all other cases, sends a verification code to the email — call [POST /api/agents/verify](/api-reference/agents/verify) with the code to get your API key.\n\n**Tip:** If you're unsure what email to register, use `agent+{Date.now()}@recoupable.com` — the current Unix timestamp in milliseconds (e.g. `agent+1744410896789@recoupable.com`). This guarantees a unique `agent+` address even when signing up multiple agents within the same second, and returns an API key instantly with no email verification required.", "security": [], "requestBody": { "description": "Agent email to register", diff --git a/index.mdx b/index.mdx index 6fd2575..17da236 100644 --- a/index.mdx +++ b/index.mdx @@ -23,7 +23,7 @@ https://recoup-api.vercel.app/api ## Authentication -Most API endpoints are authenticated using an API key passed in the `x-api-key` header. The only exceptions are the [agent onboarding](/agents) endpoints (`POST /api/agents/signup` and `POST /api/agents/verify`), which are intentionally unauthenticated so agents can obtain their first API key. +Most API endpoints are authenticated using an API key passed in the `x-api-key` header. The only exceptions are the [agent onboarding](/agents) endpoints — [`POST /api/agents/signup`](/api-reference/agents/signup) and [`POST /api/agents/verify`](/api-reference/agents/verify) — which are intentionally unauthenticated so agents can obtain their first API key. 1. Navigate to the [API Keys Management Page](https://chat.recoupable.com/keys) 2. Sign in with your account From 2c59f7a9388afb877291d61023e4a9870b1f8a96 Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Sat, 11 Apr 2026 18:46:26 -0500 Subject: [PATCH 4/6] docs: make agent signup the priority path across the docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure the top-level pages so an AI agent landing cold on the docs can copy one curl command and have a working API key. Inspired by AgentMail's quickstart layout, but the agent+ prefix trick lets us skip their OTP round-trip entirely. - index.mdx: add a "Quickest start — one curl call" section right under the hero, and promote Agent Signup to the first card in Get Started (removed the duplicate card from the Agents group below) - quickstart.mdx: lead with "## Quickest start" (single curl call using agent+$(date +%s%3N) for guaranteed uniqueness), move the dashboard path to a "Prefer the dashboard?" section at the bottom, trim the duplicated three-step onboarding block in favor of a link to /agents (closes the cubic-dev-ai DRY duplication comment) - agents.mdx: restructured as an action-first runbook — "Quickest start" heading first, single copy-paste curl block, then "How it works", with the standard email-verification flow demoted to a secondary section Mintlify already publishes /llms.txt automatically, so no action needed on that front — the new endpoints will be indexed on the next deploy. Co-Authored-By: Claude Opus 4.6 (1M context) --- agents.mdx | 51 +++++++++++++++++++----------- index.mdx | 28 ++++++++++++----- quickstart.mdx | 85 +++++++++++++++++++++----------------------------- 3 files changed, 87 insertions(+), 77 deletions(-) diff --git a/agents.mdx b/agents.mdx index 394a986..7b7bd5a 100644 --- a/agents.mdx +++ b/agents.mdx @@ -1,27 +1,16 @@ --- title: 'Agents' -description: 'Programmatic agent onboarding — sign up and obtain API keys without human intervention.' +description: 'Programmatic agent onboarding — sign up and obtain API keys in one call, no dashboard, no human in the loop.' --- -## Overview +## Quickest start -Two unauthenticated endpoints let agents create accounts and obtain API keys programmatically — no UI, no human in the loop. - -- **[`POST /api/agents/signup`](/api-reference/agents/signup)** — Register with an email address. Emails with the `agent+` prefix (e.g. `agent+mybot@example.com`) receive an API key immediately on first signup. All other cases receive a 6-digit verification code via email. -- **[`POST /api/agents/verify`](/api-reference/agents/verify)** — Submit the verification code to receive an API key. - -Multiple API keys per account are supported — each signup or verification generates a new key without revoking existing ones. - - -If you're unsure what email to register, use `agent+{Date.now()}@recoupable.com` — the current Unix timestamp in milliseconds (e.g. `agent+1744410896789@recoupable.com`). This guarantees a unique `agent+` address even if you sign up multiple agents within the same second, and returns an API key instantly without needing email verification. - - -## Instant Signup (agent+ prefix) +Get a working API key in a single unauthenticated request: ```bash curl -X POST "https://recoup-api.vercel.app/api/agents/signup" \ -H "Content-Type: application/json" \ - -d '{"email": "agent+mybot@example.com"}' + -d '{"email": "agent+'$(date +%s%3N)'@recoupable.com"}' ``` Response: @@ -34,7 +23,24 @@ Response: } ``` -## Standard Signup (email verification) +That's it. Store `api_key`, pass it in the `x-api-key` header on every subsequent request, and you're done. + + +The `agent+{Date.now()}@recoupable.com` shape guarantees a fresh address on every call — including multiple signups within the same second. This is the recommended path for agents because it always returns an API key instantly, with no email verification required. + + +## How it works + +Two unauthenticated endpoints power agent onboarding: + +- **[`POST /api/agents/signup`](/api-reference/agents/signup)** — Register with an email address. Emails with the `agent+` prefix that have never been seen before receive an API key immediately. Any other email (or a previously-used `agent+` address) receives a 6-digit verification code via email. +- **[`POST /api/agents/verify`](/api-reference/agents/verify)** — Submit the verification code to receive an API key. + +Multiple API keys per account are supported — each signup or verification generates a new key without revoking existing ones. + +## Standard signup (email verification) + +If you're building a human-facing integration and want the user to verify their real email, use any non-`agent+` address: Step 1 — request a verification code: @@ -44,7 +50,7 @@ curl -X POST "https://recoup-api.vercel.app/api/agents/signup" \ -d '{"email": "you@example.com"}' ``` -Step 2 — submit the code from the verification email: +Step 2 — submit the 6-digit code from the verification email: ```bash curl -X POST "https://recoup-api.vercel.app/api/agents/verify" \ @@ -62,6 +68,13 @@ Response: } ``` -## Next Steps +## Using your API key + +Pass the returned `api_key` in the `x-api-key` header on every authenticated request: + +```bash +curl -X GET "https://recoup-api.vercel.app/api/tasks" \ + -H "x-api-key: YOUR_API_KEY" +``` -Once you have an API key, see [Authentication](/authentication) for how to use it, and [Quickstart](/quickstart) for your first API call. +See [Authentication](/authentication) for the full authentication model, including organization access and Bearer token support, and [Quickstart](/quickstart) for your first end-to-end request. diff --git a/index.mdx b/index.mdx index 17da236..3a36098 100644 --- a/index.mdx +++ b/index.mdx @@ -7,6 +7,18 @@ description: "Use the Recoup API to build your record label. Access research, co Use the Recoup API to build your record label. Generate content, Access artist analytics, Manage catalogs, Team chats, and task automation to power your record labels. +## Quickest start — one curl call + +Get a working API key in a single unauthenticated request. No dashboard, no browser, no human in the loop. + +```bash +curl -X POST "https://recoup-api.vercel.app/api/agents/signup" \ + -H "Content-Type: application/json" \ + -d '{"email": "agent+'$(date +%s%3N)'@recoupable.com"}' +``` + +The response includes an `api_key` you can use immediately. See the [Agents guide](/agents) for the full signup and verification flow. + ## What is Recoup? Recoup is an AI agent platform for smarter song rollouts, unforgettable fan experiences, and lasting artist growth. Empowering music executives with actionable insights and next-gen tools. @@ -41,7 +53,14 @@ Keep your API key secure. Do not share it publicly or commit it to version contr ## Get Started - + + + Get an API key in one curl call. The fastest path for AI agents — no dashboard required. + Content creation agent accessible via Slack. Generates images, videos, and captions for artists automatically. - - Programmatic account creation. Get an API key with just an email address. - -See the full [Agent Signup](/api-reference/agents/signup) and [Verify](/api-reference/agents/verify) API reference for details. - - -## API Keys - -To access the Recoup API programmatically, you'll need to create an API key. - -### Step 1: Access the API Keys Management Page + +The `agent+{timestamp}@recoupable.com` shape is the fastest path for agents — it guarantees a fresh `agent+` address and returns an API key instantly without email verification. + -1. Navigate to the [Recoup API Keys Management Page](https://chat.recoupable.com/keys) -2. Sign in with your account if you haven't already +For the full signup + email-verification flow, see the [Agents guide](/agents). -### Step 2: Create Your API Key +## Base URL -1. On the API Keys page, you'll see a form to create a new API key -2. Enter a descriptive name for your API key (e.g., "My Development Key", "Production API Key") -3. Click the "Create API Key" button +All API requests should be made to: - -Copy and securely store your API key immediately - it will only be shown once! - +```bash +https://recoup-api.vercel.app/api +``` -### Step 3: Use Your API Key +## Your First Request -Once you have your API key, include it in the `x-api-key` header for all authenticated requests. Here's a simple example that retrieves your scheduled tasks: +Once you have an API key, include it in the `x-api-key` header on every request. Here's a simple call that retrieves your scheduled tasks: @@ -154,6 +126,19 @@ console.log(data.tasks); For full documentation on the Tasks API including filtering options, see the [Tasks API Reference](/api-reference/tasks/get). +## Prefer the dashboard? + +If you're a human building an integration, you can also create API keys from the web console instead of the signup endpoint: + +1. Navigate to the [Recoup API Keys Management Page](https://chat.recoupable.com/keys) +2. Sign in with your account +3. Enter a descriptive name (e.g. "Production Server") +4. Click **Create API Key** + + +Copy and securely store your API key immediately — it will only be shown once. + + ## Next Steps With your API key ready, you can now: From 2501e0d378f7472e0fd822ed107f6437a2d5f214 Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Sat, 11 Apr 2026 18:58:24 -0500 Subject: [PATCH 5/6] docs: add env-var one-liner to agent signup flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the returned api_key straight into \$RECOUP_API_KEY in a single shell command, so agents can pipe signup → usage with no intermediate copy-paste step. - index.mdx: the Quickest Start block now exports RECOUP_API_KEY directly - quickstart.mdx: same one-liner, plus a verification call using the exported env var - agents.mdx: added a dedicated Tip callout showing both the signup one-liner and a follow-up request against /api/accounts/id Co-Authored-By: Claude Opus 4.6 (1M context) --- agents.mdx | 16 ++++++++++++++++ index.mdx | 6 +++--- quickstart.mdx | 16 ++++++---------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/agents.mdx b/agents.mdx index 7b7bd5a..c72ddac 100644 --- a/agents.mdx +++ b/agents.mdx @@ -25,6 +25,22 @@ Response: That's it. Store `api_key`, pass it in the `x-api-key` header on every subsequent request, and you're done. + +**One-liner — sign up and export the key in one shot.** Drop this into your shell and you'll have `$RECOUP_API_KEY` ready to use on the next line: + +```bash +export RECOUP_API_KEY=$(curl -s -X POST "https://recoup-api.vercel.app/api/agents/signup" \ + -H "Content-Type: application/json" \ + -d '{"email": "agent+'$(date +%s%3N)'@recoupable.com"}' | jq -r .api_key) +``` + +Verify it worked: + +```bash +curl -H "x-api-key: $RECOUP_API_KEY" https://recoup-api.vercel.app/api/accounts/id +``` + + The `agent+{Date.now()}@recoupable.com` shape guarantees a fresh address on every call — including multiple signups within the same second. This is the recommended path for agents because it always returns an API key instantly, with no email verification required. diff --git a/index.mdx b/index.mdx index 3a36098..ee0d0e3 100644 --- a/index.mdx +++ b/index.mdx @@ -12,12 +12,12 @@ Use the Recoup API to build your record label. Generate content, Access artist a Get a working API key in a single unauthenticated request. No dashboard, no browser, no human in the loop. ```bash -curl -X POST "https://recoup-api.vercel.app/api/agents/signup" \ +export RECOUP_API_KEY=$(curl -s -X POST "https://recoup-api.vercel.app/api/agents/signup" \ -H "Content-Type: application/json" \ - -d '{"email": "agent+'$(date +%s%3N)'@recoupable.com"}' + -d '{"email": "agent+'$(date +%s%3N)'@recoupable.com"}' | jq -r .api_key) ``` -The response includes an `api_key` you can use immediately. See the [Agents guide](/agents) for the full signup and verification flow. +`$RECOUP_API_KEY` is now ready to pass in the `x-api-key` header on any request. See the [Agents guide](/agents) for the full signup and verification flow. ## What is Recoup? diff --git a/quickstart.mdx b/quickstart.mdx index e026e5c..a954d43 100644 --- a/quickstart.mdx +++ b/quickstart.mdx @@ -5,22 +5,18 @@ description: "Get a Recoup API key in one call and make your first request — n ## Quickest start -Sign up your agent and get an API key in a single API call — no dashboard, no browser. +Sign up your agent and get an API key in a single API call — no dashboard, no browser, no human in the loop. This one-liner signs up a fresh `agent+` address and exports the returned key to `$RECOUP_API_KEY`: ```bash -curl -X POST "https://recoup-api.vercel.app/api/agents/signup" \ +export RECOUP_API_KEY=$(curl -s -X POST "https://recoup-api.vercel.app/api/agents/signup" \ -H "Content-Type: application/json" \ - -d '{"email": "agent+'$(date +%s%3N)'@recoupable.com"}' + -d '{"email": "agent+'$(date +%s%3N)'@recoupable.com"}' | jq -r .api_key) ``` -Response: +Verify it worked: -```json -{ - "account_id": "123e4567-e89b-12d3-a456-426614174000", - "api_key": "recoup_sk_abc123...", - "message": "If this is a new agent+ email, your API key is included. Otherwise, check your email for a verification code." -} +```bash +curl -H "x-api-key: $RECOUP_API_KEY" https://recoup-api.vercel.app/api/accounts/id ``` From f786b58889e46d3f19f2992a8e5d74050d7b9ed1 Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Sat, 11 Apr 2026 19:06:30 -0500 Subject: [PATCH 6/6] docs: use portable date+RANDOM for agent signup suffix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit \`date +%s%3N\` is a GNU coreutils extension — on macOS's BSD \`date\`, \`%3N\` is output literally, producing a broken, non-unique email like \`agent+17449811573N@recoupable.com\`. Since most developers copy-pasting our quickstart are on macOS, this would silently give them duplicate suffixes within the same second and confuse the \`agent+\` onboarding flow. Switch to \`\$(date +%s)-\$RANDOM\`, which is: - Portable across BSD/GNU \`date\` (POSIX \`%s\` only) - Collision-free within a single second (bash/zsh \`\$RANDOM\` adds 0–32767 of entropy per call) - Still trivially readable in curl examples Applied in index.mdx, quickstart.mdx, agents.mdx, and the /api/agents/signup OpenAPI description. Co-Authored-By: Claude Opus 4.6 (1M context) --- agents.mdx | 6 +++--- api-reference/openapi/accounts.json | 2 +- index.mdx | 2 +- quickstart.mdx | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/agents.mdx b/agents.mdx index c72ddac..8bbf1f0 100644 --- a/agents.mdx +++ b/agents.mdx @@ -10,7 +10,7 @@ Get a working API key in a single unauthenticated request: ```bash curl -X POST "https://recoup-api.vercel.app/api/agents/signup" \ -H "Content-Type: application/json" \ - -d '{"email": "agent+'$(date +%s%3N)'@recoupable.com"}' + -d '{"email": "agent+'$(date +%s)-$RANDOM'@recoupable.com"}' ``` Response: @@ -31,7 +31,7 @@ That's it. Store `api_key`, pass it in the `x-api-key` header on every subsequen ```bash export RECOUP_API_KEY=$(curl -s -X POST "https://recoup-api.vercel.app/api/agents/signup" \ -H "Content-Type: application/json" \ - -d '{"email": "agent+'$(date +%s%3N)'@recoupable.com"}' | jq -r .api_key) + -d '{"email": "agent+'$(date +%s)-$RANDOM'@recoupable.com"}' | jq -r .api_key) ``` Verify it worked: @@ -42,7 +42,7 @@ curl -H "x-api-key: $RECOUP_API_KEY" https://recoup-api.vercel.app/api/accounts/ -The `agent+{Date.now()}@recoupable.com` shape guarantees a fresh address on every call — including multiple signups within the same second. This is the recommended path for agents because it always returns an API key instantly, with no email verification required. +The `agent+{unique-suffix}@recoupable.com` shape is the recommended path for agents — it always returns an API key instantly, with no email verification required. Combining `$(date +%s)` with `$RANDOM` guarantees a fresh, collision-free address on every call (including multiple signups within the same second) and is portable across macOS and Linux shells. ## How it works diff --git a/api-reference/openapi/accounts.json b/api-reference/openapi/accounts.json index 6e84d0e..9bd3a76 100644 --- a/api-reference/openapi/accounts.json +++ b/api-reference/openapi/accounts.json @@ -1466,7 +1466,7 @@ }, "/api/agents/signup": { "post": { - "description": "Register an agent. For new agent+ emails, returns an API key immediately. For all other cases, sends a verification code to the email — call [POST /api/agents/verify](/api-reference/agents/verify) with the code to get your API key.\n\n**Tip:** If you're unsure what email to register, use `agent+{Date.now()}@recoupable.com` — the current Unix timestamp in milliseconds (e.g. `agent+1744410896789@recoupable.com`). This guarantees a unique `agent+` address even when signing up multiple agents within the same second, and returns an API key instantly with no email verification required.", + "description": "Register an agent. For new agent+ emails, returns an API key immediately. For all other cases, sends a verification code to the email — call [POST /api/agents/verify](/api-reference/agents/verify) with the code to get your API key.\n\n**Tip:** If you're unsure what email to register, generate a unique `agent+{suffix}@recoupable.com` address (e.g. `agent+1744410896-28439@recoupable.com`, combining a Unix timestamp with a random integer). This guarantees a fresh `agent+` address on every call — including multiple signups within the same second — and returns an API key instantly with no email verification required.", "security": [], "requestBody": { "description": "Agent email to register", diff --git a/index.mdx b/index.mdx index ee0d0e3..62bb714 100644 --- a/index.mdx +++ b/index.mdx @@ -14,7 +14,7 @@ Get a working API key in a single unauthenticated request. No dashboard, no brow ```bash export RECOUP_API_KEY=$(curl -s -X POST "https://recoup-api.vercel.app/api/agents/signup" \ -H "Content-Type: application/json" \ - -d '{"email": "agent+'$(date +%s%3N)'@recoupable.com"}' | jq -r .api_key) + -d '{"email": "agent+'$(date +%s)-$RANDOM'@recoupable.com"}' | jq -r .api_key) ``` `$RECOUP_API_KEY` is now ready to pass in the `x-api-key` header on any request. See the [Agents guide](/agents) for the full signup and verification flow. diff --git a/quickstart.mdx b/quickstart.mdx index a954d43..95dd61b 100644 --- a/quickstart.mdx +++ b/quickstart.mdx @@ -10,7 +10,7 @@ Sign up your agent and get an API key in a single API call — no dashboard, no ```bash export RECOUP_API_KEY=$(curl -s -X POST "https://recoup-api.vercel.app/api/agents/signup" \ -H "Content-Type: application/json" \ - -d '{"email": "agent+'$(date +%s%3N)'@recoupable.com"}' | jq -r .api_key) + -d '{"email": "agent+'$(date +%s)-$RANDOM'@recoupable.com"}' | jq -r .api_key) ``` Verify it worked: