> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orsay.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 🔑 REST API

> Programmatic access to Orsay via API key

## Overview

The Orsay REST API allows you to manage sequences and access conversations programmatically from your own server. This is useful for:

* Automating sequence creation from a VPS or cron job
* Integrating Orsay into your existing pipeline (e.g., Instagram → DM sequence)
* Building custom automations without going through the dashboard
* Retrieving conversation data for your CRM or analytics tools

## Authentication

All API requests require a **Bearer token** using your API key.

```bash theme={null}
curl -X GET https://client.api.prod.orsay.ai/api/v1/sequences \
  -H "Authorization: Bearer sk_live_your_api_key_here"
```

### Getting your API key

1. Go to **Settings → API Keys** in the Orsay dashboard
2. Click **Generate API Key**
3. Copy the key immediately — it won't be shown again

<Warning>
  Your API key gives full access to your organization's sequences. Keep it secret and never expose it in client-side code.
</Warning>

## Rate Limiting

The API is rate-limited to **200 requests per hour** per organization.

If you exceed this limit, you'll receive a `429 Too Many Requests` response with a `Retry-After` header indicating how many seconds to wait.

## Base URL

```
https://client.api.prod.orsay.ai/api/v1
```

## Endpoints

### List Agents

```bash theme={null}
GET /agents
```

Returns all AI agents for your organization.

**Response:**

```json theme={null}
[
  {
    "id": "e5f6g7h8-...",
    "name": "Sales Agent",
    "is_published": true
  }
]
```

***

### List Profiles

```bash theme={null}
GET /profiles
```

Returns all connected Instagram and WhatsApp profiles.

**Response:**

```json theme={null}
{
  "instagram": [
    {
      "id": "12345678",
      "username": "mybusiness",
      "status": "CONNECTED"
    }
  ],
  "whatsapp": [
    {
      "id": "abcd-1234-...",
      "name": "My WhatsApp",
      "status": "CONNECTED"
    }
  ]
}
```

***

### List Sequences

```bash theme={null}
GET /sequences
```

Returns all sequences for your organization.

**Response:**

```json theme={null}
[
  {
    "id": "a1b2c3d4-...",
    "name": "Welcome DM",
    "trigger": "INSTAGRAM_MESSAGE",
    "channel": "INSTAGRAM",
    "active": true
  }
]
```

***

### Get Sequence

```bash theme={null}
GET /sequences/{sequence_id}
```

Returns full details of a specific sequence.

**Response:**

```json theme={null}
{
  "id": "a1b2c3d4-...",
  "name": "Welcome DM",
  "trigger": "INSTAGRAM_MESSAGE",
  "channel": "INSTAGRAM",
  "active": true,
  "type": "INBOUND",
  "agent_id": "e5f6g7h8-...",
  "profile_id": "12345",
  "inbound_response_delay": 5,
  "inbound_response_delay_unit": "MINUTES",
  "flow": [
    {
      "delay": 0,
      "delay_unit": "MINUTES",
      "content": "Hello! How can I help you?",
      "template_id": null,
      "action": null
    }
  ]
}
```

***

### Create Sequence

```bash theme={null}
POST /sequences
```

**Request body:**

```json theme={null}
{
  "name": "My New Sequence",
  "trigger": "INSTAGRAM_MESSAGE",
  "inbound_response_delay": 5,
  "inbound_response_delay_unit": "MINUTES",
  "agent_id": "e5f6g7h8-...",
  "profile_id": "12345",
  "active": false,
  "flow": [
    {
      "delay": 0,
      "delay_unit": "MINUTES",
      "followup_delays": [
        { "delay": 30, "delay_unit": "MINUTES" }
      ]
    }
  ]
}
```

**Required fields:**

| Field     | Type   | Description              |
| --------- | ------ | ------------------------ |
| `name`    | string | Name of the sequence     |
| `trigger` | string | Trigger type (see below) |

**Optional fields:**

| Field                                    | Type   | Default   | Description                      |
| ---------------------------------------- | ------ | --------- | -------------------------------- |
| `inbound_response_delay`                 | int    | 5         | Delay before first response      |
| `inbound_response_delay_unit`            | string | "MINUTES" | SECONDS, MINUTES, or HOURS       |
| `agent_id`                               | string | null      | AI agent ID to use               |
| `profile_id`                             | string | null      | Instagram or WhatsApp profile ID |
| `active`                                 | bool   | false     | Whether the sequence is active   |
| `flow`                                   | array  | \[]       | Flow steps definition            |
| `filtering_agent`                        | string | null      | Filtering agent ID               |
| `should_continue_existing_conversations` | bool   | false     | Continue existing conversations  |
| `keywords`                               | array  | null      | Trigger keywords                 |
| `target_accounts`                        | array  | null      | Target accounts for scraping     |
| `enable_agent_on_conversation`           | bool   | true      | Enable AI agent on conversations |
| `require_manual_approval`                | bool   | false     | Require manual message approval  |

**Response (201):**

```json theme={null}
{
  "id": "new-sequence-uuid"
}
```

***

### Update Sequence

```bash theme={null}
PUT /sequences/{sequence_id}
```

Only include the fields you want to update.

**Request body:**

```json theme={null}
{
  "name": "Updated Name",
  "active": true,
  "inbound_response_delay": 10
}
```

**Response:**

```json theme={null}
{
  "id": "a1b2c3d4-...",
  "status": "updated"
}
```

***

### Delete Sequence

```bash theme={null}
DELETE /sequences/{sequence_id}
```

**Response:**

```json theme={null}
{
  "status": "deleted"
}
```

***

### List Conversations

```bash theme={null}
GET /conversations
```

Returns conversations for your organization with optional filters.

**Query parameters:**

| Parameter        | Type    | Default | Description                                                                 |
| ---------------- | ------- | ------- | --------------------------------------------------------------------------- |
| `classification` | string  | null    | Filter by classification: `positive`, `negative`, `undetermined`, `engaged` |
| `is_active`      | boolean | null    | Filter by active (`true`) or inactive (`false`) status                      |
| `since`          | string  | null    | ISO 8601 date — only return conversations updated after this date           |
| `page_size`      | int     | 20      | Number of results per page (max 50)                                         |
| `last_lead_id`   | string  | null    | Cursor for pagination (use `next_cursor` from previous response)            |

**Example:**

```bash theme={null}
curl -X GET "https://client.api.prod.orsay.ai/api/v1/conversations?classification=positive&is_active=true&page_size=10" \
  -H "Authorization: Bearer sk_live_your_api_key_here"
```

**Response:**

```json theme={null}
{
  "conversations": [
    {
      "lead_id": "a1b2c3d4-...",
      "channel": "WHATSAPP",
      "classification": "positive",
      "is_active": true,
      "first_name": "John",
      "last_name": "Doe",
      "username": null,
      "phone_number": "+33612345678",
      "latest_message_at": "2025-06-01T14:30:00+00:00",
      "latest_inbound_at": "2025-06-01T14:30:00+00:00",
      "latest_outbound_at": "2025-06-01T14:25:00+00:00"
    }
  ],
  "next_cursor": "a1b2c3d4-..."
}
```

<Note>
  Use `next_cursor` as the `last_lead_id` parameter in subsequent requests to paginate through results. When `next_cursor` is `null`, there are no more results.
</Note>

***

### Get Conversation Messages

```bash theme={null}
GET /conversations/{lead_id}
```

Returns the full message history of a conversation.

**Path parameters:**

| Parameter | Type | Description                     |
| --------- | ---- | ------------------------------- |
| `lead_id` | UUID | The lead ID of the conversation |

**Example:**

```bash theme={null}
curl -X GET "https://client.api.prod.orsay.ai/api/v1/conversations/a1b2c3d4-5678-90ab-cdef-1234567890ab" \
  -H "Authorization: Bearer sk_live_your_api_key_here"
```

**Response:**

```json theme={null}
{
  "lead_id": "a1b2c3d4-...",
  "channel": "WHATSAPP",
  "classification": "positive",
  "is_active": true,
  "lead": {
    "first_name": "John",
    "last_name": "Doe",
    "username": null,
    "phone_number": "+33612345678"
  },
  "messages": [
    {
      "message_id": "msg-uuid-1",
      "content": "Hello! How can I help you?",
      "inbound": false,
      "timestamp": "2025-06-01T14:00:00+00:00",
      "status": "DELIVERED",
      "sent_by": "ai",
      "type": "CUSTOM"
    },
    {
      "message_id": "msg-uuid-2",
      "content": "I'd like to know more about your services",
      "inbound": true,
      "timestamp": "2025-06-01T14:05:00+00:00",
      "status": null,
      "sent_by": null,
      "type": null
    }
  ],
  "total_messages": 2
}
```

## Trigger Types

| Trigger                                         | Channel   | Type     |
| ----------------------------------------------- | --------- | -------- |
| `INSTAGRAM_MESSAGE`                             | Instagram | Inbound  |
| `INSTAGRAM_COMMENT`                             | Instagram | Outbound |
| `INSTAGRAM_STORY_REPLY`                         | Instagram | Inbound  |
| `INSTAGRAM_LEAD_FINDER_NEW_FOLLOWER`            | Instagram | Outbound |
| `INSTAGRAM_LEAD_FINDER_OTHER_ACCOUNT_FOLLOWERS` | Instagram | Outbound |
| `INSTAGRAM_LEAD_FINDER_NEW_LIKE`                | Instagram | Outbound |
| `INSTAGRAM_LEAD_FINDER_OTHER_ACCOUNT_COMMENT`   | Instagram | Outbound |
| `WHATSAPP_MESSAGE`                              | WhatsApp  | Inbound  |
| `CONTACT_CREATED`                               | WhatsApp  | Outbound |
| `CONTACT_SUBSCRIBED_TO_SEQUENCE`                | WhatsApp  | Outbound |

## Error Codes

| Code  | Description                                                             |
| ----- | ----------------------------------------------------------------------- |
| `401` | Invalid or missing API key                                              |
| `404` | Resource not found (sequence or conversation)                           |
| `429` | Rate limit exceeded (200 req/hour)                                      |
| `400` | Invalid request (bad trigger, missing field, invalid date format, etc.) |

## Example: Full Pipeline

```python theme={null}
import requests
import time

API_KEY = "sk_live_your_key_here"
BASE_URL = "https://client.api.prod.orsay.ai/api/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

# 1. List sequences
sequences = requests.get(f"{BASE_URL}/sequences", headers=HEADERS).json()
print(f"Found {len(sequences)} sequences")

# 2. Create a new sequence
new_seq = requests.post(f"{BASE_URL}/sequences", headers=HEADERS, json={
    "name": "Auto DM Pipeline",
    "trigger": "INSTAGRAM_MESSAGE",
    "inbound_response_delay": 2,
    "inbound_response_delay_unit": "MINUTES",
    "agent_id": "your-agent-id",
    "profile_id": "your-instagram-profile-id",
    "active": True,
    "flow": [
        {
            "delay": 0,
            "delay_unit": "MINUTES",
            "followup_delays": [
                {"delay": 30, "delay_unit": "MINUTES"},
                {"delay": 120, "delay_unit": "MINUTES"}
            ]
        }
    ]
}).json()
print(f"Created sequence: {new_seq['id']}")

# 3. Update it later
time.sleep(1)  # Small delay between requests
requests.put(f"{BASE_URL}/sequences/{new_seq['id']}", headers=HEADERS, json={
    "name": "Auto DM Pipeline v2",
    "inbound_response_delay": 5,
})
```
