- Base URL:
https://studio-api-prod.suno.com - Auth: Clerk-based. Browser has Clerk session cookies → exchanges for JWT → JWT used as
Authorization: Bearer <jwt> - Required headers:
authorization: Bearer <jwt>device-id: <uuid>(from browser, persisted)browser-token: {"token":"<base64({"timestamp":<ms>})>"}(dynamic, generated per-request)origin: https://suno.comreferer: https://suno.com/
- JWT lifetime: ~1 hour. Auto-refreshed by Clerk SDK in browser.
- Clerk session ID: Found in JWT
sidclaim (e.g.,session_eece6e4f36131cbcb12aeb)
/api/billing/info/returns the active plan, remaining credits, usage period, feature flags, model list, and model limits.- Do not commit live account-specific credit balances to this file; they drift quickly and are not useful as implementation evidence.
| Display Name | External Key | Default | Max Prompt | Max Tags | Max Neg Tags | Max GPT Desc |
|---|---|---|---|---|---|---|
| v5.5 | chirp-fenix |
YES | 5000 | 1000 | 1000 | 500 |
| v5 | chirp-crow |
No | 5000 | 1000 | 1000 | 500 |
| v4.5+ | chirp-bluejay |
No | 5000 | 1000 | 1000 | 500 |
| v4.5 | chirp-auk |
No | 5000 | 1000 | 1000 | 500 |
| v4.5-all | chirp-auk-turbo |
Free default | 5000 | 1000 | 1000 | 500 |
| v4 | chirp-v4 |
No | 3000 | 200 | 1000 | 500 |
| v3.5 | chirp-v3-5 |
No | 3000 | 200 | 1000 | 500 |
| v3 | chirp-v3-0 |
No | 1250 | 200 | 1000 | 500 |
| v2 | chirp-v2-xxl-alpha |
No | 1250 | 200 | 1000 | 500 |
| Name | Key |
|---|---|
| v5.5 (default) | chirp-flounder |
| v5 | chirp-carp |
| v4.5+ | chirp-bass |
Returns full account info, credits, plan, models, features, limits.
Request: {"prompt": "description of song"}
Response: {"id": "<uuid>"} (async — poll for result)
Response (when complete):
{
"text": "[Verse 1]\n...\n[Chorus]\n...",
"title": "Generated Title",
"status": "complete",
"error_message": "",
"tags": ["style description auto-generated by Suno"]
}Generate music. Payload shape captured from the current web route and represented by src/api/types.rs::GenerateRequest:
{
"make_instrumental": false,
"mv": "chirp-fenix",
"prompt": "",
"generation_type": "TEXT",
"continue_at": null,
"continue_clip_id": null,
"metadata": {
"web_client_pathname": "/create",
"create_mode": "custom",
"create_session_token": "<uuid>"
},
"token": "<captcha_token>",
"tags": "pop, upbeat, synths",
"title": "Summer Vibes",
"negative_tags": "metal, heavy, dark"
}IMPORTANT: Some accounts/flows require a fresh hCaptcha token field. The Rust CLI uses a piloted Chrome path when needed and also accepts --token for externally supplied solutions. Do not send a token_provider field: the v2-web endpoint 422s on the string (verified 2026; the CLI dropped it), so only token rides on the request body. Whether a captcha is needed at all is answered by the preflight below.
Captcha preflight (verified live 2026-07-18 on both studio-api-prod.suno.com and studio-api.prod.suno.com). Request: {"ctype": "generation"} with Bearer JWT. Response: {"required": false, "captcha_version": 1} — required is false for accounts above Suno's trust threshold, so the solver can be skipped entirely. When required is true, generating one song in the suno.com UI clears the challenge.
Two modes:
- Description mode (
metadata.create_mode = "inspiration",promptis the description) — Suno writes lyrics from description - Custom mode (
metadata.create_mode = "custom",prompt= lyrics,tags+title+negative_tagsset)
Response: {"clips": [...], "metadata": {...}, "status": "..."}
Concatenate/extend clips. {"clip_id": "<id>"}
Request: {"cursor": "<opaque next_cursor from previous response>", "limit": 20, "filters": {...}} — omit cursor for the first page. Page numbers are NOT accepted.
Response: {"clips": [...], "next_cursor": "...", "has_more": true}
Clip structure:
id, title, status, model_name, audio_url, audio_url_2, video_url,
image_url, image_large_url, created_at, play_count, upvote_count,
metadata: { tags, prompt, duration, avg_bpm, min_bpm, max_bpm,
has_stem, is_mumble, is_remix, make_instrumental, type,
can_remix, priority, stream, uses_latest_model }
User's playlists. Returns {"num_total_results": N, "current_page": N, "playlists": [...]}
Trending clips. Returns playlist-like structure.
Stem separation. Endpoint per gcui-art/paean-ai evidence; implemented in
src/api/stems.rs. (An earlier capture guessed /api/generate/stems/ —
wrong path.)
Cover generation (not tested, likely needs POST).
Remaster with different model (not tested).
Full pipeline for creating a Voice persona from audio:
The S3 presigned upload happens first (not captured here), then:
POST /api/uploads/audio/{upload_id}/upload-finish/
Response: 200 OK (empty body, content-length: 2)
GET /api/uploads/audio/{upload_id}/
Response: JSON with processing status.
POST /api/processed_clip/voice-vox-stem
Content-Length: ~90 bytes
Extracts clean vocals from uploaded audio. Body likely: {"upload_id": "<id>"}.
Called multiple times — once per upload (sample + verification).
User reads: "Listening to the melody of a gentle summer breeze" Second upload goes through the same upload-finish flow with a new upload_id.
POST /api/voice-verification/
Content-Length: 179 bytes
Verifies the voice matches. Body likely includes both upload IDs + verification text.
POST /api/persona/create/
Content-Length: 47261 bytes (large — likely includes audio data as base64)
Creates the voice persona from the verified audio clips.
POST /api/uploads/audio/{id}/upload-finish/— mark upload completeGET /api/uploads/audio/{id}/— poll upload processingPOST /api/processed_clip/voice-vox-stem— extract vocalsPOST /api/voice-verification/— verify voice samplePOST /api/persona/create/— create voice persona (47KB payload)
Need to capture the REQUEST BODIES (not just headers) to see exact JSON payloads. The S3 presigned upload step (before upload-finish) also needs capturing.
- Captcha is the main challenge — generation requires a captcha token that gcui-art solves via Playwright browser automation
- Lyrics generation is free and easy — no captcha needed, just JWT auth
- JWT refresh — need Clerk cookie exchange or session keepalive
- Browser-token header — dynamically generated from current timestamp, base64-encoded
- Cookie-based approach — store Clerk session cookies, exchange for JWT via
auth.suno.com/v1/client/sessions/<session_id>/tokens - Two auth strategies: a. Cookie-based: Store browser cookies, auto-refresh JWT (what gcui-art does) b. Direct JWT: User pastes JWT, works for ~1 hour (simpler but expires)