# Suno API Intelligence — Reverse-Engineered April 6, 2026
## Auth
- **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.com`
- `referer: https://suno.com/`
- **JWT lifetime**: ~1 hour. Auto-refreshed by Clerk SDK in browser.
- **Clerk session ID**: Found in JWT `sid` claim (e.g., `session_eece6e4f36131cbcb12aeb`)
## Account — Premier Plan
- Credits: 10,755 total remaining
- Monthly: 45/10,000 used
- Period ends: 2026-05-01
- Features: v4, cover, edit_mode, persona, stems, negative_tags, remaster, video, custom_models, etc.
## Models (from /api/billing/info/)
| **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 |
### Remaster Models
| v5.5 (default) | `chirp-flounder` |
| v5 | `chirp-carp` |
| v4.5+ | `chirp-bass` |
## Verified Endpoints
### GET /api/billing/info/
Returns full account info, credits, plan, models, features, limits.
### POST /api/generate/lyrics/
**Request**: `{"prompt": "description of song"}`
**Response**: `{"id": "<uuid>"}` (async — poll for result)
### GET /api/generate/lyrics/{id}
**Response** (when complete):
```json
{
"text": "[Verse 1]\n...\n[Chorus]\n...",
"title": "Generated Title",
"status": "complete",
"error_message": "",
"tags": ["style description auto-generated by Suno"]
}
```
### POST /api/generate/v2/
**Generate music**. Payload (from gcui-art/suno-api source):
```json
{
"make_instrumental": false,
"mv": "chirp-fenix",
"prompt": "",
"generation_type": "TEXT",
"continue_at": null,
"continue_clip_id": null,
"task": null,
"token": "<captcha_token>",
"gpt_description_prompt": "a happy pop song about summer",
"tags": "pop, upbeat, synths",
"title": "Summer Vibes",
"negative_tags": "metal, heavy, dark"
}
```
**IMPORTANT**: Requires `token` field (captcha). gcui-art uses Playwright to intercept browser captcha flow.
**Two modes**:
1. **Description mode** (`gpt_description_prompt` set, `prompt` empty) — Suno writes lyrics from description
2. **Custom mode** (`prompt` = lyrics, `tags` + `title` + `negative_tags` set)
**Response**: `{"clips": [...], "metadata": {...}, "status": "..."}`
### POST /api/generate/concat/v2/
Concatenate/extend clips. `{"clip_id": "<id>"}`
### POST /api/feed/v3
**Request**: `{"page": 0}`
**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 }
```
### GET /api/playlist/me
User's playlists. Returns `{"num_total_results": N, "current_page": N, "playlists": [...]}`
### GET /api/trending/
Trending clips. Returns playlist-like structure.
### POST /api/generate/stems/
Stem separation (not tested, needs POST).
### POST /api/cover/
Cover generation (not tested, likely needs POST).
### POST /api/remaster/
Remaster with different model (not tested).
## Voices / Persona Creation Flow (captured April 6, 2026)
Full pipeline for creating a Voice persona from audio:
### Step 1: Upload initial voice sample
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)
### Step 2: Poll upload status
```
GET /api/uploads/audio/{upload_id}/
```
Response: JSON with processing status.
### Step 3: Extract vocal stem
```
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).
### Step 4: Record & upload verification phrase
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.
### Step 5: Voice verification
```
POST /api/voice-verification/
Content-Length: 179 bytes
```
Verifies the voice matches. Body likely includes both upload IDs + verification text.
### Step 6: Create persona
```
POST /api/persona/create/
Content-Length: 47261 bytes (large — likely includes audio data as base64)
```
Creates the voice persona from the verified audio clips.
### Endpoints summary:
- `POST /api/uploads/audio/{id}/upload-finish/` — mark upload complete
- `GET /api/uploads/audio/{id}/` — poll upload processing
- `POST /api/processed_clip/voice-vox-stem` — extract vocals
- `POST /api/voice-verification/` — verify voice sample
- `POST /api/persona/create/` — create voice persona (47KB payload)
### To implement in CLI:
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.
## Key Insights for Rust CLI
1. **Captcha is the main challenge** — generation requires a captcha token that gcui-art solves via Playwright browser automation
2. **Lyrics generation is free and easy** — no captcha needed, just JWT auth
3. **JWT refresh** — need Clerk cookie exchange or session keepalive
4. **Browser-token header** — dynamically generated from current timestamp, base64-encoded
5. **Cookie-based approach** — store Clerk session cookies, exchange for JWT via `auth.suno.com/v1/client/sessions/<session_id>/tokens`
6. **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)