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
- Log in to your Chatlane account
- Navigate to Settings → API Tokens
- Click "Create Token"
- Enter a name for your token (e.g., "Zapier Integration")
- Select the team to scope the token to
- 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- Success201- Created400- Bad Request401- Unauthenticated403- Forbidden404- Not Found422- Validation Error500- 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 IDstatus(string) - Filter by status:active,pending,closedcontact_id(integer) - Filter entity-record conversations to ones where this contact has sent or received at least one message. Pass eithercontact_idorcontact_email, not both. Returns an empty page when the contact does not exist in the team.contact_email(string) - Same ascontact_idbut lookup by email — useful when the calling system stores the contact's email but not their Chatlane id. Matching is case-insensitive and trimmed.limit(integer, default: 50, max: 100) - Number of results per pageoffset(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}"
Surfacing conversations for a single contact:
curl -X GET "https://chatlane.io/api/v1/[email protected]" \
-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.
Query Parameters:
contact_id/contact_email(optional) - On an entity-record conversation, pre-filter the embeddedmessagesarray to that contact's thread (sender orrecipient_contact_id). The conversation itself is still returned in full.
Example Request:
curl -X GET "https://chatlane.io/api/v1/conversations/1" \
-H "Authorization: Bearer {your-token}"
Fetching only one contact's thread within an entity conversation:
curl -X GET "https://chatlane.io/api/v1/conversations/[email protected]" \
-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
bodyfield is optional on conversation creation. - If
bodyis 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:
- Create the conversation (with or without
body). - Then create one or more messages using the Message endpoint:
POST /api/v1/conversations/{conversationId}/messages.
- Create the conversation (with or without
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 IDinbox_id(integer) - Filter by inbox IDtype(string) - Filter by message type:email,sms,whatsapp,note,phone_call,facebook,instagramcontact_id/contact_email- On entity-record conversations, narrow to messages to or from this contact (sender orrecipient_contact_id). Activity rows are excluded by this endpoint regardless.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}"
Fetching one contact's thread within a shared entity conversation:
curl -X GET "https://chatlane.io/api/v1/messages?conversation_id=42&[email protected]" \
-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 contenttype(required, string) - Message type:email,sms,whatsapp,note,phone_call,facebook,instagramis_draft(boolean, default: false) - Iftrue, message is saved as draft. Iffalse, 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 attachcontact_id(integer, optional) - The contact the message is addressed to. Required for entity record conversations, except whensender_typeiscontact— a contact-authored message is inbound (addressed to your team, not to a peer), so it is recorded with no recipient.record_only(boolean, default: false) - Log a message that was already sent or received by another system into the conversation history without dispatching delivery. Nothing is sent; the message is stored withdelivery_status: sent.cc(string, optional) - CC recipients (comma-separated)bcc(string, optional) - BCC recipients (comma-separated)sender_type(string, optional) - Type of sender:user,contact, oragent. 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 whensender_typeis 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_typeandsender_idare not provided, the message sender defaults to the authenticated user associated with the API token. - When specifying a custom sender:
- Both
sender_typeandsender_idare required. sender_type: "user"→sender_idmust be a user that belongs to the same team.sender_type: "contact"→sender_idmust be a contact in the same team.sender_type: "agent"→sender_idmust be an agent in the same team.
- Both
Recording an inbound message from a contact:
Use this to mirror something a contact did in your own system (a form submission, a quote, a reply you already emailed them about) into the Chatlane conversation, so your team can reply to them from the inbox.
curl -X POST "https://chatlane.io/api/v1/conversations/1/messages" \
-H "Authorization: Bearer {your-token}" \
-H "Content-Type: application/json" \
-d '{
"body": "<p>I have submitted my quote for this order.</p>",
"type": "email",
"record_only": true,
"sender_type": "contact",
"sender_id": 456
}'
Omitting contact_id is what marks the message as inbound — recipient_contact_id stays null, exactly like a message that genuinely arrived from the contact. Pair it with record_only: true whenever your own system has already delivered the message, so Chatlane records it without sending anything.
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 pageemail(string, optional) - Filter contacts by exact email addressphone_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.
Automation: Identify & Track
These two endpoints power Chatlane Automation (segments, broadcasts, and workflows). They mirror the identify/track pattern used by tools like Customer.io, so existing integrations translate directly. See the Automation articles for how this data is used.
Identify Contact (Upsert + Attributes)
POST /api/v1/contacts/identify
Find a contact by id, email, or phone number — creating them if no match exists — and sync typed marketing attributes onto their profile. Attributes are the building blocks of segment rules (e.g. currency equals GBP, total_spend ≥ 1000).
Request Body:
{
"identifiers": { "email": "[email protected]" },
"name": "Jane Doe",
"attributes": {
"currency": "GBP",
"locale": "en-GB",
"total_orders": 4,
"total_spend": 1240.50,
"vip": true,
"signed_up_at": "2026-01-15"
}
}
identifiers(object, required) - One ofid(Chatlane contact id),email, orphone_number. Resolution priority is id → email → phone. Phone numbers must be real, valid numbers in international format (e.g.+447911123456) — identify validates them because it may create or update the contact. (Track only uses the phone to look a contact up, so it skips this check.)name(string, optional) - Set or update the contact's name.attributes(object, optional) - Flat map of scalar values. Keys may contain letters, digits, underscores, dashes and dots. Types are inferred from the first value seen for each key (number, boolean, date, or text) and drive which operators segments offer.
Responses:
201- Contact created (returns the contact resource)200- Existing contact updated404with codeCONTACT_NOT_FOUND- An internalidwas given that doesn't exist, and no email/phone was provided to create from422- Non-scalar attribute values, unsafe attribute keys, or an invalidphone_numberidentifier
Example Request:
curl -X POST "https://chatlane.io/api/v1/contacts/identify" \
-H "Authorization: Bearer {your-token}" \
-H "Content-Type: application/json" \
-d '{
"identifiers": { "email": "[email protected]" },
"attributes": { "currency": "GBP", "total_spend": 1240.50 }
}'
Note: Identify writes to the contact's typed attribute store used by Automation. It never touches the custom_attributes JSON field used by the Create/Update Contact endpoints above.
Track Event
POST /api/v1/events
Record an event against a contact — e.g. request_quote, place_order, approve_order. Events power segment rules ("performed X at least N times in the last Y days"), trigger workflows, and attribute workflow conversions.
Request Body:
{
"identifiers": { "email": "[email protected]" },
"name": "place_order",
"properties": {
"order_total": 420.50,
"service": "Certified Translation"
},
"timestamp": 1753400000,
"id": "order-12345"
}
identifiers(object, required) -id,email, orphone_numberof an existing contactname(string, required) - Event name; use consistent snake_case (letters, digits,_,-,., spaces)properties(object, optional) - Event payload. Filterable in segment and workflow rules ("where propertyserviceequalsCertified Translation"), and used for conversion values (e.g.order_total)timestamp(integer, optional) - Unix timestamp of when the event occurred; defaults to nowid(string, optional) - Idempotency key. Re-sending the same key is a no-op, so you can safely retry
Responses:
201with{"event_id": 123}- Event recorded200with{"duplicate": true}- Idempotency key already used; nothing recorded404with codeCONTACT_NOT_FOUND- No contact matches the identifiers. Track never auto-creates contacts — call identify first
Example Request:
curl -X POST "https://chatlane.io/api/v1/events" \
-H "Authorization: Bearer {your-token}" \
-H "Content-Type: application/json" \
-d '{
"identifiers": { "email": "[email protected]" },
"name": "request_quote",
"properties": { "service": "Certified Translation", "quote_value": 250 },
"id": "quote-9876"
}'
Recommended integration order: call identify when a customer signs up or their profile changes, then track for each meaningful action. Segments re-evaluate automatically within seconds of each call.
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 IDlimit(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 thevaluesobject.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 invalues, theexternal_idfield 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.
Link Contact to Record
POST /api/v1/custom-entity-records/{id}/contacts
Attach a contact to a custom entity record with a role (e.g. the people on an order). In a single request you can either reference an existing contact by contact_id, or pass contact details (email/name/phone_number) to find or create the contact, then attach it.
Request Body:
{
"email": "[email protected]",
"name": "Jamie Chen",
"role": "client"
}
Parameters:
contact_id(optional, integer) - Attach an existing contact by id.email(optional, string) - Find a contact by email, or create one if none exists.name(optional, string) - Name used when creating a new contact.phone_number(optional, string) - E.164 phone; used to find or create the contact.custom_attributes(optional, object) - Stored on the contact when it is created.role(optional, string) - The contact's role on this record (must match a role defined on the custom entity, e.g.client,vendor,project_manager,team_member).
You must provide at least one of contact_id, email, or name.
Behaviour:
- Find-or-create: with no
contact_id, the contact is looked up byemailthenphone_number; if none matches a new contact is created. - Idempotent: a contact can only be attached to a record once. Re-posting the same contact updates its
roleinstead of creating a duplicate. - The record and contact must belong to the token's team.
Example Request:
curl -X POST "https://chatlane.io/api/v1/custom-entity-records/1/contacts" \
-H "Authorization: Bearer {your-token}" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"name": "Jamie Chen",
"role": "client"
}'
Example Response (201):
{
"message": "Contact attached successfully",
"data": {
"id": 10,
"custom_entity_record_id": 1,
"contact_id": 42,
"team_id": 1,
"role": "client",
"contact": {
"id": 42,
"name": "Jamie Chen",
"email": "[email protected]",
"phone_number": null
},
"created_at": "2026-06-05T10:00:00Z",
"updated_at": "2026-06-05T10:00:00Z"
}
}
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
Generate API Token:
- Log in to Chatlane
- Go to Settings → API Tokens
- Create a new token for your Zapier integration
- Copy the token value
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
Create Triggers:
- Use polling triggers with
created_afterparameter - Example:
GET /api/v1/conversations?created_after={last_poll_time}
- Use polling triggers with
Create Actions:
- Use POST endpoints to create resources
- Example:
POST /api/v1/conversations/{id}/messagesto 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 pollstatus: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 neither linked to the entity record nor a participant in the conversation |
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
- Polling: Use
created_afterparameter with ISO 8601 timestamps for efficient polling - Pagination: Always handle pagination using
linksandmetain responses - Error Handling: Check HTTP status codes and error response structure
- Rate Limiting: Implement exponential backoff for rate limit errors
- Token Security: Store tokens securely and never expose them in client-side code
- Team Scoping: Remember that tokens are scoped to specific teams
Support
For API support, contact [email protected] or browse the help center.