Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 202 additions & 21 deletions openhands/usage/cloud/cloud-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,206 @@ To use the OpenHands Cloud API, you'll need to generate an API key:
4. Give your key a descriptive name (Example: "Development" or "Production") and select `Create`.
5. Copy the generated API key and store it securely. It will only be shown once.

## API Usage Example
## API Usage Example (V1)

### Starting a New Conversation

To start a new conversation with OpenHands to perform a task,
you'll need to make a POST request to the conversation endpoint.
make a POST request to the V1 app-conversations endpoint.

<Tabs>
<Tab title="cURL">
```bash
curl -X POST "https://app.all-hands.dev/api/v1/app-conversations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"initial_message": {
"content": [{"type": "text", "text": "Check whether there is any incorrect information in the README.md file and send a PR to fix it if so."}]
},
"selected_repository": "yourusername/your-repo"
}'
```
</Tab>
<Tab title="Python (with requests)">
```python
import requests

api_key = "YOUR_API_KEY"
url = "https://app.all-hands.dev/api/v1/app-conversations"

headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}

data = {
"initial_message": {
"content": [{"type": "text", "text": "Check whether there is any incorrect information in the README.md file and send a PR to fix it if so."}]
},
"selected_repository": "yourusername/your-repo"
}

response = requests.post(url, headers=headers, json=data)
result = response.json()

# The response contains a start task with the conversation ID
conversation_id = result.get("app_conversation_id") or result.get("id")
print(f"Conversation Link: https://app.all-hands.dev/conversations/{conversation_id}")
print(f"Status: {result['status']}")
```
</Tab>
<Tab title="TypeScript/JavaScript (with fetch)">
```typescript
const apiKey = "YOUR_API_KEY";
const url = "https://app.all-hands.dev/api/v1/app-conversations";

const headers = {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
};

const data = {
initial_message: {
content: [{ type: "text", text: "Check whether there is any incorrect information in the README.md file and send a PR to fix it if so." }]
},
selected_repository: "yourusername/your-repo"
};

async function startConversation() {
try {
const response = await fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(data)
});

const result = await response.json();

// The response contains a start task with the conversation ID
const conversationId = result.app_conversation_id || result.id;
console.log(`Conversation Link: https://app.all-hands.dev/conversations/${conversationId}`);
console.log(`Status: ${result.status}`);

return result;
} catch (error) {
console.error("Error starting conversation:", error);
}
}

startConversation();
```
</Tab>
</Tabs>

#### Response

The API will return a JSON object with details about the conversation start task:

```json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "WORKING",
"app_conversation_id": "660e8400-e29b-41d4-a716-446655440001",
"sandbox_id": "sandbox-abc123",
"created_at": "2025-01-15T10:30:00Z"
}
```

The `status` field indicates the current state of the conversation startup process:
- `WORKING` - Initial processing
- `WAITING_FOR_SANDBOX` - Waiting for sandbox to be ready
- `PREPARING_REPOSITORY` - Cloning and setting up the repository
- `READY` - Conversation is ready to use
- `ERROR` - An error occurred during startup

You may receive an authentication error if:

- You provided an invalid API key.
- You provided the wrong repository name.
- You don't have access to the repository.

### Streaming Conversation Start (Optional)

For real-time updates during conversation startup, you can use the streaming endpoint:

```bash
curl -X POST "https://app.all-hands.dev/api/v1/app-conversations/stream-start" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"initial_message": {
"content": [{"type": "text", "text": "Your task description here"}]
},
"selected_repository": "yourusername/your-repo"
}'
```

#### Streaming Response

The endpoint streams a JSON array incrementally. Each element represents a status update:

```json
[
{"id": "550e8400-e29b-41d4-a716-446655440000", "status": "WORKING", "created_at": "2025-01-15T10:30:00Z"},
{"id": "550e8400-e29b-41d4-a716-446655440000", "status": "WAITING_FOR_SANDBOX", "created_at": "2025-01-15T10:30:00Z"},
{"id": "550e8400-e29b-41d4-a716-446655440000", "status": "PREPARING_REPOSITORY", "created_at": "2025-01-15T10:30:00Z"},
{"id": "550e8400-e29b-41d4-a716-446655440000", "status": "READY", "app_conversation_id": "660e8400-e29b-41d4-a716-446655440001", "sandbox_id": "sandbox-abc123", "created_at": "2025-01-15T10:30:00Z"}
]
```

Each update is streamed as it occurs, allowing you to provide real-time feedback to users about the conversation startup progress.

## Rate Limits

If you have too many conversations running at once, older conversations will be paused to limit the number of concurrent conversations.
If you're running into issues and need a higher limit for your use case, please contact us at [contact@all-hands.dev](mailto:contact@all-hands.dev).

---

## Migrating from V0 to V1 API

<Warning>
The V0 API (`/api/conversations`) is deprecated and scheduled for removal on **April 1, 2026**.
Copy link

@jlav jlav Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we ever send any comms about about the April 1 date? I know there are references in the code to an April 1 removal date, but unless all our API users are keenly watching our codebase...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we sent any comms, maybe we should. But at least this is better than in the codebase.

Please migrate to the V1 API (`/api/v1/app-conversations`) as soon as possible.
</Warning>

### Key Differences

| Feature | V0 API | V1 API |
|---------|--------|--------|
| Endpoint | `POST /api/conversations` | `POST /api/v1/app-conversations` |
| Message format | `initial_user_msg` (string) | `initial_message.content` (array of content objects) |
| Repository field | `repository` | `selected_repository` |
| Response | Immediate `conversation_id` | Start task with `status` and eventual `app_conversation_id` |

### Migration Steps

1. **Update the endpoint URL**: Change from `/api/conversations` to `/api/v1/app-conversations`

2. **Update the request body**:
- Change `repository` to `selected_repository`
- Change `initial_user_msg` (string) to `initial_message` (object with content array):
```json
// V0 format
{ "initial_user_msg": "Your message here" }

// V1 format
{ "initial_message": { "content": [{"type": "text", "text": "Your message here"}] } }
```

3. **Update response handling**: The V1 API returns a start task object. The conversation ID is in the `app_conversation_id` field (available when status is `READY`), or use the `id` field for the start task ID.

---

## Legacy API (V0) - Deprecated

<Warning>
The V0 API is deprecated since version 1.0.0 and will be removed on **April 1, 2026**.
New integrations should use the V1 API documented above.
</Warning>

### Starting a New Conversation (V0)

<Tabs>
<Tab title="cURL">
Expand Down Expand Up @@ -59,9 +253,9 @@ you'll need to make a POST request to the conversation endpoint.
print(f"Conversation Link: https://app.all-hands.dev/conversations/{conversation['conversation_id']}")
print(f"Status: {conversation['status']}")
```
</Tab>
<Tab title="TypeScript/JavaScript (with fetch)">
```typescript
</Tab>
<Tab title="TypeScript/JavaScript (with fetch)">
```typescript
const apiKey = "YOUR_API_KEY";
const url = "https://app.all-hands.dev/api/conversations";

Expand All @@ -85,7 +279,7 @@ you'll need to make a POST request to the conversation endpoint.

const conversation = await response.json();

console.log(`Conversation Link: https://app.all-hands.dev/conversations/${conversation.id}`);
console.log(`Conversation Link: https://app.all-hands.dev/conversations/${conversation.conversation_id}`);
console.log(`Status: ${conversation.status}`);

return conversation;
Expand All @@ -99,24 +293,11 @@ you'll need to make a POST request to the conversation endpoint.
</Tab>
</Tabs>

#### Response

The API will return a JSON object with details about the created conversation:
#### Response (V0)

```json
{
"status": "ok",
"conversation_id": "abc1234",
"conversation_id": "abc1234"
}
```

You may receive an `AuthenticationError` if:

- You provided an invalid API key.
- You provided the wrong repository name.
- You don't have access to the repository.

## Rate Limits

If you have too many conversations running at once, older conversations will be paused to limit the number of concurrent conversations.
If you're running into issues and need a higher limit for your use case, please contact us at [contact@all-hands.dev](mailto:contact@all-hands.dev).