REST API v1

Chatlane API documentation

Endpoints, auth, and webhook reference

Base URL
https://chatlane.io/api/v1/
⌘K
Try in Postman

Overview

The Chatlane API provides a RESTful interface for accessing and managing conversations, messages, contacts, and custom entity records. The API uses API Key authentication via Laravel Sanctum.

Base URL

All API endpoints are prefixed with /api/v1/:

https://chatlane.io/api/v1/

Authentication

The API uses Bearer token authentication. Include your API token in the Authorization header:

Authorization: Bearer {your-api-token}

Generating API Tokens

  1. Log in to your Chatlane account
  2. Navigate to Settings → API Tokens
  3. Click "Create Token"
  4. Enter a name for your token (e.g., "Zapier Integration")
  5. Select the team to scope the token to
  6. Copy the token value immediately (it will not be shown again)

Important: API tokens are scoped to a specific team. The token can only access data from that team.

Rate Limiting

API requests are rate-limited. Contact support if you need higher limits.

Response Format

Success Response

All successful responses return JSON with the following structure:

Single Resource:

{
  "data": {
    "id": 1,
    "name": "Example",
    "created_at": "2026-01-26T10:00:00Z"
  }
}

Collection (Paginated):

{
  "data": [
    {
      "id": 1,
      "name": "Example 1"
    },
    {
      "id": 2,
      "name": "Example 2"
    }
  ],
  "links": {
    "first": "https://chatlane.io/api/v1/resource?page=1",
    "last": "https://chatlane.io/api/v1/resource?page=2",
    "prev": null,
    "next": "https://chatlane.io/api/v1/resource?page=2"
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 2,
    "path": "https://chatlane.io/api/v1/resource",
    "per_page": 50,
    "to": 50,
    "total": 100
  }
}

Error Response

Error responses follow this format:

{
  "error": "Error message",
  "code": "ERROR_CODE",
  "details": {}
}

HTTP Status Codes

  • 200 - Success
  • 201 - Created
  • 400 - Bad Request
  • 401 - Unauthenticated
  • 403 - Forbidden
  • 404 - Not Found
  • 422 - Validation Error
  • 500 - Server Error

Endpoints

Conversations

List Conversations

GET /api/v1/conversations

List conversations with optional filtering.

Query Parameters:

  • created_after (string, ISO 8601) - Filter conversations created after this timestamp (for polling)
  • inbox_id (integer) - Filter by inbox ID
  • status (string) - Filter by status: active, pending, closed
  • limit (integer, default: 50, max: 100) - Number of results per page
  • offset (integer) - Pagination offset

Example Request:

curl -X GET "https://chatlane.io/api/v1/conversations?created_after=2026-01-26T00:00:00Z&status=active" \
  -H "Authorization: Bearer {your-token}"

Example Response:

{
  "data": [
    {
      "id": 1,
      "subject": "Customer inquiry",
      "status": "active",
      "is_read": false,
      "is_archived": false,
      "is_starred": false,
      "last_message_at": "2026-01-26T10:30:00Z",
      "inbox": {
        "id": 1,
        "name": "Support",
        "type": "standard"
      },
      "participant": {
        "id": 1,
        "name": "John Doe",
        "email": "[email protected]"
      },
      "assignee": null,
      "created_at": "2026-01-26T10:00:00Z",
      "updated_at": "2026-01-26T10:30:00Z"
    }
  ],
  "links": {...},
  "meta": {...}
}

Get Single Conversation

GET /api/v1/conversations/{id}

Get detailed information about a specific conversation, including messages.

Example Request:

curl -X GET "https://chatlane.io/api/v1/conversations/1" \
  -H "Authorization: Bearer {your-token}"

Example Response:

{
  "data": {
    "id": 1,
    "subject": "Customer inquiry",
    "status": "active",
    "inbox": {...},
    "participant": {...},
    "messages": [
      {
        "id": 1,
        "body": "Hello, I need help with...",
        "type": "email",
        "delivery_status": "sent",
        "created_at": "2026-01-26T10:00:00Z"
      }
    ],
    "assignee": {...},
    "created_at": "2026-01-26T10:00:00Z",
    "updated_at": "2026-01-26T10:30:00Z"
  }
}

Create Conversation

POST /api/v1/conversations

Create a new conversation.

Request Body:

{
  "inbox_id": 1,
  "contact_id": 123,
  "subject": "New conversation",
  "body": "Initial message content",
  "status": "active",
  "tags": ["vip", "billing", "priority"]
}

For Entity Inboxes:

{
  "inbox_id": 2,
  "custom_entity_record_id": 456,
  "subject": "New conversation",
  "body": "Initial message content",
  "status": "active",
  "tags": ["shipment", "high_value"]
}

Example Request:

curl -X POST "https://chatlane.io/api/v1/conversations" \
  -H "Authorization: Bearer {your-token}" \
  -H "Content-Type: application/json" \
  -d '{
    "inbox_id": 1,
    "contact_id": 123,
    "subject": "New conversation",
    "tags": ["vip", "billing"]
  }'

Notes:

  • The body field is optional on conversation creation.
  • If body is provided, an initial email message is created automatically with that content.
  • For full control over message delivery (type, draft status, channel, attachments, etc.), the recommended pattern is:
    1. Create the conversation (with or without body).
    2. Then create one or more messages using the Message endpoint:
      POST /api/v1/conversations/{conversationId}/messages.

Example Response:

{
  "data": {
    "id": 1,
    "subject": "New conversation",
    "status": "active",
    "tags": [
      {
        "id": 10,
        "name": "vip",
        "color": "#3b82f6"
      },
      {
        "id": 11,
        "name": "billing",
        "color": "#3b82f6"
      }
    ],
    "created_at": "2026-01-26T10:00:00Z"
  }
}

Messages

List Messages

GET /api/v1/messages

List messages with optional filtering.

Query Parameters:

  • created_after (string, ISO 8601) - Filter messages created after this timestamp (for polling)
  • conversation_id (integer) - Filter by conversation ID
  • inbox_id (integer) - Filter by inbox ID
  • type (string) - Filter by message type: email, sms, whatsapp, note, phone_call, facebook, instagram
  • limit (integer, default: 50, max: 100) - Number of results per page

Example Request:

curl -X GET "https://chatlane.io/api/v1/messages?conversation_id=1&type=email" \
  -H "Authorization: Bearer {your-token}"

Example Response:

{
  "data": [
    {
      "id": 1,
      "body": "Hello, I need help with...",
      "type": "email",
      "delivery_status": "sent",
      "is_read": false,
      "conversation": {
        "id": 1,
        "subject": "Customer inquiry"
      },
      "sender": {
        "id": 1,
        "name": "John Doe",
        "email": "[email protected]"
      },
      "created_at": "2026-01-26T10:00:00Z"
    }
  ],
  "links": {...},
  "meta": {...}
}

Get Single Message

GET /api/v1/messages/{id}

Get detailed information about a specific message.

Example Request:

curl -X GET "https://chatlane.io/api/v1/messages/1" \
  -H "Authorization: Bearer {your-token}"

Example Response:

{
  "data": {
    "id": 1,
    "body": "Hello, I need help with...",
    "type": "email",
    "delivery_status": "sent",
    "is_read": false,
    "external_message_id": null,
    "attachments": [],
    "conversation": {
      "id": 1,
      "subject": "Customer inquiry",
      "status": "active"
    },
    "channel": {
      "id": 1,
      "name": "Email Channel",
      "type": "email",
      "is_active": true
    },
    "sender": {
      "id": 1,
      "name": "John Doe",
      "email": "[email protected]"
    },
    "created_at": "2026-01-26T10:00:00Z",
    "updated_at": "2026-01-26T10:00:00Z"
  }
}

Create Message

POST /api/v1/conversations/{conversationId}/messages

Create a new message in a conversation.

Request Body:

{
  "body": "Message content",
  "type": "email",
  "is_draft": false,
  "inbox_channel_id": 123,
  "file_urls": [
    "https://example.com/file1.pdf",
    "https://example.com/file2.jpg"
  ],
  "cc": "[email protected]",
  "bcc": "[email protected]",
  "sender_type": "contact",
  "sender_id": 456
}

Parameters:

  • body (required, string) - Message content
  • type (required, string) - Message type: email, sms, whatsapp, note, phone_call, facebook, instagram
  • is_draft (boolean, default: false) - If true, message is saved as draft. If false, message is sent immediately.
  • inbox_channel_id (integer, optional) - Specific channel to use. If not provided, uses first active channel of the specified type.
  • file_urls (array, optional) - Array of publicly accessible file URLs to download and attach
  • contact_id (integer, optional) - Required for entity record conversations
  • cc (string, optional) - CC recipients (comma-separated)
  • bcc (string, optional) - BCC recipients (comma-separated)
  • sender_type (string, optional) - Type of sender: user, contact, or agent. If omitted, the sender defaults to the authenticated user.
  • sender_id (integer, optional) - ID of the sender model. Must belong to the same team. Required when sender_type is provided.

Example Request:

curl -X POST "https://chatlane.io/api/v1/conversations/1/messages" \
  -H "Authorization: Bearer {your-token}" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Thank you for your inquiry!",
    "type": "email",
    "is_draft": false,
    "sender_type": "contact",
    "sender_id": 456
  }'

Notes:

  • If sender_type and sender_id are not provided, the message sender defaults to the authenticated user associated with the API token.
  • When specifying a custom sender:
    • Both sender_type and sender_id are required.
    • sender_type: "user"sender_id must be a user that belongs to the same team.
    • sender_type: "contact"sender_id must be a contact in the same team.
    • sender_type: "agent"sender_id must be an agent in the same team.

Example Response:

{
  "data": {
    "id": 1,
    "body": "Thank you for your inquiry!",
    "type": "email",
    "delivery_status": "sending",
    "is_read": true,
    "external_message_id": null,
    "attachments": [],
    "conversation": {
      "id": 1,
      "subject": "Customer inquiry",
      "status": "active"
    },
    "channel": {
      "id": 1,
      "name": "Email Channel",
      "type": "email",
      "is_active": true
    },
    "sender": {
      "id": 2,
      "name": "Support Agent",
      "email": "[email protected]"
    },
    "created_at": "2026-01-26T10:00:00Z",
    "updated_at": "2026-01-26T10:00:00Z"
  }
}

Contacts

List Contacts

GET /api/v1/contacts

List contacts with optional filtering.

Query Parameters:

  • created_after (string, ISO 8601) - Filter contacts created after this timestamp (for polling)
  • limit (integer, default: 50, max: 100) - Number of results per page
  • email (string, optional) - Filter contacts by exact email address
  • phone_number (string, optional) - Filter contacts by phone number. The number will be normalized to E.164 format before matching.

Example Request:

curl -X GET "https://chatlane.io/api/v1/contacts" \
  -H "Authorization: Bearer {your-token}"

Example: Find Contact by Email

curl -X GET "https://chatlane.io/api/v1/[email protected]" \
  -H "Authorization: Bearer {your-token}"

Example: Find Contact by Phone Number

curl -X GET "https://chatlane.io/api/v1/contacts?phone_number=+441234567890" \
  -H "Authorization: Bearer {your-token}"

Both filters can be combined; results are always scoped to the authenticated token's team and returned as a paginated list (even if only a single contact matches).

Get Single Contact

GET /api/v1/contacts/{id}

Get detailed information about a specific contact.

Example Request:

curl -X GET "https://chatlane.io/api/v1/contacts/1" \
  -H "Authorization: Bearer {your-token}"

Create Contact

POST /api/v1/contacts

Create a new contact.

Request Body:

{
  "name": "John Doe",
  "email": "[email protected]",
  "phone_number": "+1234567890",
  "custom_attributes": {
    "company": "Acme Corp",
    "role": "Manager"
  }
}

Example Request:

curl -X POST "https://chatlane.io/api/v1/contacts" \
  -H "Authorization: Bearer {your-token}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "email": "[email protected]"
  }'

Update Contact

PUT/PATCH /api/v1/contacts/{id}

Update an existing contact. All fields are optional - only provided fields will be updated.

Request Body:

{
  "name": "Jane Doe",
  "email": "[email protected]",
  "phone_number": "+1987654321",
  "custom_attributes": {
    "company": "New Corp",
    "role": "Director",
    "department": "Engineering"
  }
}

Example Request:

curl -X PUT "https://chatlane.io/api/v1/contacts/1" \
  -H "Authorization: Bearer {your-token}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Jane Doe",
    "email": "[email protected]",
    "custom_attributes": {
      "company": "New Corp",
      "role": "Director"
    }
  }'

Example Response:

{
  "data": {
    "id": 1,
    "name": "Jane Doe",
    "email": "[email protected]",
    "phone_number": "+1987654321",
    "custom_attributes": {
      "company": "New Corp",
      "role": "Director",
      "department": "Engineering"
    },
    "created_at": "2026-01-26T10:00:00Z",
    "updated_at": "2026-01-26T11:00:00Z"
  }
}

Note: If you update the email or phone number to a value that already exists for another contact in your team, you will receive a 422 error with code DUPLICATE_EMAIL or DUPLICATE_PHONE.

Custom Entity Records

List Custom Entity Records

GET /api/v1/custom-entity-records

List custom entity records with optional filtering.

Query Parameters:

  • created_after (string, ISO 8601) - Filter records created after this timestamp (for polling)
  • custom_entity_id (integer) - Filter by custom entity ID
  • limit (integer, default: 50, max: 100) - Number of results per page

Example Request:

curl -X GET "https://chatlane.io/api/v1/custom-entity-records?custom_entity_id=1" \
  -H "Authorization: Bearer {your-token}"

Example Response:

{
  "data": [
    {
      "id": 1,
      "custom_entity_id": 1,
      "external_id": "EXT-12345",
      "values": {
        "name": "Order #12345",
        "status": "pending"
      },
      "custom_entity": {
        "id": 1,
        "name": "Orders",
        "slug": "orders"
      },
      "created_at": "2026-01-26T10:00:00Z",
      "updated_at": "2026-01-26T10:00:00Z"
    }
  ],
  "links": {...},
  "meta": {...}
}

Get Single Custom Entity Record

GET /api/v1/custom-entity-records/{id}

Get detailed information about a specific custom entity record.

Example Request:

curl -X GET "https://chatlane.io/api/v1/custom-entity-records/1" \
  -H "Authorization: Bearer {your-token}"

Example Response:

{
  "data": {
    "id": 1,
    "custom_entity_id": 1,
    "external_id": "EXT-12345",
    "values": {
      "name": "Order #12345",
      "status": "pending",
      "amount": 99.99
    },
    "custom_entity": {
      "id": 1,
      "name": "Orders",
      "slug": "orders",
      "attributes": [...]
    },
    "conversations": [...],
    "contacts": [...],
    "created_at": "2026-01-26T10:00:00Z",
    "updated_at": "2026-01-26T10:00:00Z"
  }
}

Create Custom Entity Record

POST /api/v1/custom-entity-records

Create a new custom entity record. The custom_entity_id is required to specify which custom entity type this record belongs to.

Request Body:

{
  "custom_entity_id": 1,
  "external_id": "EXT-12345",
  "values": {
    "name": "Order #12345",
    "status": "pending",
    "amount": 99.99
  }
}

Parameters:

  • custom_entity_id (required, integer) - The ID of the custom entity this record belongs to. Must exist and belong to your team.
  • external_id (optional, string) - An external identifier for the record. If not provided and the custom entity has an external_id attribute defined, it will be extracted from the values object.
  • values (required, object) - The record's attribute values. Must match the custom entity's attribute definitions.

Example Request:

curl -X POST "https://chatlane.io/api/v1/custom-entity-records" \
  -H "Authorization: Bearer {your-token}" \
  -H "Content-Type: application/json" \
  -d '{
    "custom_entity_id": 1,
    "values": {
      "name": "Order #12345",
      "status": "pending"
    }
  }'

Example Response:

{
  "data": {
    "id": 1,
    "custom_entity_id": 1,
    "external_id": "Order #12345",
    "values": {
      "name": "Order #12345",
      "status": "pending"
    },
    "custom_entity": {
      "id": 1,
      "name": "Orders",
      "slug": "orders"
    },
    "created_at": "2026-01-26T10:00:00Z",
    "updated_at": "2026-01-26T10:00:00Z"
  }
}

Note: The custom_entity_id is always included in the response, even when the custom_entity relationship is not loaded. This allows you to identify which custom entity type the record belongs to without needing to load the full relationship.

Update Custom Entity Record

PUT/PATCH /api/v1/custom-entity-records/{id}

Update an existing custom entity record. You can update the values object and/or the external_id.

Request Body:

{
  "external_id": "EXT-12345-UPDATED",
  "values": {
    "name": "Order #12345",
    "status": "completed",
    "amount": 149.99
  }
}

Parameters:

  • external_id (optional, string) - Update the external identifier for the record.
  • values (optional, object) - Update the record's attribute values. If provided, must match the custom entity's attribute definitions. If the custom entity has an external_id attribute defined and you update that value in values, the external_id field will be automatically updated.

Example Request:

curl -X PUT "https://chatlane.io/api/v1/custom-entity-records/1" \
  -H "Authorization: Bearer {your-token}" \
  -H "Content-Type: application/json" \
  -d '{
    "values": {
      "name": "Order #12345",
      "status": "completed",
      "amount": 149.99
    }
  }'

Example Response:

{
  "data": {
    "id": 1,
    "custom_entity_id": 1,
    "external_id": "EXT-12345",
    "values": {
      "name": "Order #12345",
      "status": "completed",
      "amount": 149.99
    },
    "custom_entity": {
      "id": 1,
      "name": "Orders",
      "slug": "orders"
    },
    "created_at": "2026-01-26T10:00:00Z",
    "updated_at": "2026-01-26T11:00:00Z"
  }
}

Note: When updating values, you can provide a partial update (only the fields you want to change) or a complete update (all fields). The custom_entity_id cannot be changed after creation.

Inboxes (Read-Only)

List Inboxes

GET /api/v1/inboxes

List all inboxes for reference (read-only).

Example Request:

curl -X GET "https://chatlane.io/api/v1/inboxes" \
  -H "Authorization: Bearer {your-token}"

Get Single Inbox

GET /api/v1/inboxes/{id}

Get information about a specific inbox (read-only).

Example Request:

curl -X GET "https://chatlane.io/api/v1/inboxes/1" \
  -H "Authorization: Bearer {your-token}"

Zapier Integration

Setting Up Zapier

  1. Generate API Token:

    • Log in to Chatlane
    • Go to Settings → API Tokens
    • Create a new token for your Zapier integration
    • Copy the token value
  2. Configure Zapier:

    • In your Zapier app, add API Key authentication
    • Use the token as the API key
    • Set the Base URL to: https://chatlane.io/api/v1
  3. Create Triggers:

    • Use polling triggers with created_after parameter
    • Example: GET /api/v1/conversations?created_after={last_poll_time}
  4. Create Actions:

    • Use POST endpoints to create resources
    • Example: POST /api/v1/conversations/{id}/messages to send messages

Example Zapier Trigger (New Conversations)

Polling URL: https://chatlane.io/api/v1/conversations

Query Parameters:

  • created_after: Use the timestamp from your last poll
  • status: active (optional)

Sample Response:

{
  "data": [
    {
      "id": 1,
      "subject": "New customer inquiry",
      "status": "active",
      "participant": {
        "name": "John Doe",
        "email": "[email protected]"
      }
    }
  ]
}

Example Zapier Action (Send Message)

Action URL: https://chatlane.io/api/v1/conversations/{conversation_id}/messages

Method: POST

Headers:

Authorization: Bearer {your-token}
Content-Type: application/json

Body:

{
  "body": "{{message_body}}",
  "type": "email",
  "is_draft": false
}

Error Codes

Code Description
UNAUTHENTICATED No valid API token provided
UNAUTHORIZED Token is valid but user lacks permission
NOT_FOUND Resource not found
VALIDATION_ERROR Request validation failed
TEAM_ACCESS_DENIED Token is not valid for the requested team
INVALID_CHANNEL Specified channel is not active or does not match message type
NO_CHANNEL_FOUND No active channel of the specified type found
CONTACT_REQUIRED Contact must be specified for entity record conversations
CONTACT_NOT_ASSOCIATED Specified contact is not associated with the entity record
NO_EMAIL_ADDRESS Contact does not have an email address
NOTE_CANNOT_BE_DRAFT Notes cannot be saved as drafts
MESSAGE_TOO_LONG Message exceeds maximum length (e.g., 1600 chars for WhatsApp)
DUPLICATE_EMAIL Contact with this email already exists
DUPLICATE_PHONE Contact with this phone number already exists

Best Practices

  1. Polling: Use created_after parameter with ISO 8601 timestamps for efficient polling
  2. Pagination: Always handle pagination using links and meta in responses
  3. Error Handling: Check HTTP status codes and error response structure
  4. Rate Limiting: Implement exponential backoff for rate limit errors
  5. Token Security: Store tokens securely and never expose them in client-side code
  6. Team Scoping: Remember that tokens are scoped to specific teams

Support

For API support, contact [email protected] or browse the help center.