# Orpheus Onboarding Chat API

This document outlines how to integrate a simple chat interface to guide a new user through creating their first song. The goal is to receive confirmation that a song generation has started, at which point the chat UI can be dismissed and the user can be transitioned to the main app experience to await their song.

## Base URL
All endpoints are relative to the deployed server URL.
Example: `https://chat.suno.com`

## Core Flow

The interaction is a simple loop: the client gets messages, sends a user message, and then polls for the updated message list until the assistant's response is complete or a song is being generated.

### 1. Starting or Resuming a Chat

To begin, the client needs a unique identifier for the chat session.

- **New User**: Generate a standard `UUID` on the client side. This will be the `chat_uuid`.
- **Existing User**: Retrieve the `chat_uuid` stored from a previous session.

Then, fetch the message history. If it's a new chat, this will create the session on the server and return the initial greeting message.

**Endpoint:** `GET /api/chat/{chat_uuid}/messages`

**Method:** `GET`

**Example Request:**
```swift
// Using URLSession in Swift
let chatUUID = "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
let url = URL(string: "https://chat.suno.com/api/chat/\(chatUUID)/messages")!
let request = URLRequest(url: url)

URLSession.shared.dataTask(with: request) { data, response, error in
    // Handle response
}.resume()
```

**Example Response (New Chat):**
A JSON array containing a single `Message` object.

```jsonc
[
    {
        "chat_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
        "role": "assistant",
        "content": "Alright, let's get to it. First, what should I call you?",
        "status": "complete",
        "timestamp": "2023-10-27T10:00:00.000Z",
        "metadata": {}
    }
]
```
> **Implementation Note:** Your app should display the `content` of the messages to the user.

---

### 2. Sending a User's Message

When the user sends a message, `POST` it to the message endpoint. You must include the user's Suno API token in the request body.

**Endpoint:** `POST /api/chat/{chat_uuid}/message`

**Method:** `POST`

**Headers:**
`Content-Type: application/json`

**Request Body:**
```json
{
  "content": "The user's message text here.",
  "token": "YOUR_SUNO_BEARER_TOKEN"
}
```

**Response:**
The API will respond **immediately** with the current list of messages, which now includes the user's message and a placeholder "pending" message from the assistant. This allows you to show an "Orpheus is typing..." state.

```jsonc
[
  // ... previous messages
  {
    "chat_id": "...",
    "role": "user",
    "content": "The user's message text here.",
    "status": "complete",
    ...
  },
  {
    "chat_id": "...",
    "role": "assistant",
    "content": "Orpheus is working...",
    "status": "pending",
    ...
  }
]
```

---

### 3. Getting the Assistant's Response (Polling)

After sending a message, you must poll the `GET /api/chat/{chat_uuid}/messages` endpoint to receive the actual response.

**Polling Logic:**
1. After your `POST` request, wait 1-2 seconds.
2. Call `GET /api/chat/{chat_uuid}/messages`.
3. Check the `status` of the **last message** in the returned array.
   - If `status` is **`pending`**, the assistant is still processing. Wait another 2-3 seconds and go back to step 2.
   - If `status` is **`complete`** or **`error`**, the response is ready. Update the UI with the new message `content` and stop polling.
   - **Crucially for this flow**, check the `metadata` of the message (see Step 4).

---

### 4. Detecting Song Creation and Finishing the Flow

The primary goal of this onboarding chat is to trigger a song. When the assistant does this, the message will have specific metadata. This is your signal to exit the chat.

**The Signal:**
When polling for messages, inspect the last message from the assistant. If its `metadata` object contains `type: "song_generation_pending"`, the song has been successfully submitted to Suno's API.

**Example "Song Started" Message:**
Your polling will receive a message list where the last message looks like this.

```jsonc
{
    "chat_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "role": "assistant",
    "content": "**Song generation started**\n\nYour audio is being generated. This may take a minute or two.\n\nsong:f6b97f4e-ce69-4f8b-ae51-301d6dba6a62\nsong:e1c2d3b4-a5f6-7b8c-9d0e-1f2a3b4c5d6e",
    "status": "pending", // Status might still be pending, but that's ok.
    "timestamp": "2023-10-27T10:05:00.000Z",
    "metadata": {
        "clips": [
            {
                "id": "f6b97f4e-ce69-4f8b-ae51-301d6dba6a62",
                "title": "Your Song Title",
                "status": "submitted",
                // ...other details
            },
            {
                "id": "e1c2d3b4-a5f6-7b8c-9d0e-1f2a3b4c5d6e",
                "title": "Your Song Title",
                "status": "submitted",
                // ...other details
            }
        ],
        "type": "song_generation_pending", // <-- THIS IS THE KEY
        "async_work_in_progress": true,
        "generation_request_id": "some-uuid"
    }
}
```

**Action:**
1.  Check if `lastMessage.metadata?.type == "song_generation_pending"`.
2.  If it is, extract the clip ID(s) from `lastMessage.metadata.clips[...].id`.
3.  You now have the ID of the song being generated. You can **stop polling**, dismiss the chat interface, and transition the user to the main app experience, where you can monitor the song's completion using the main Suno API and the `clip_id`.

## Data Model

### Message Object
```typescript
interface Message {
  chat_id: string;          // The UUID of the chat session
  role: 'user' | 'assistant'; // Who sent the message
  content: string;          // The message text (Markdown formatted)
  status: 'complete' | 'pending' | 'error'; // The state of the message
  timestamp: string;        // ISO 8601 timestamp
  metadata: { [key: string]: any }; // Contains extra data, like clip info
}
``` 
