PHPackages                             sashalenz/chatwoot-api - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. sashalenz/chatwoot-api

ActiveLibrary[API Development](/categories/api)

sashalenz/chatwoot-api
======================

Chatwoot Application API SDK for Laravel — thin REST client for contacts, conversations and messages (API-channel bridge).

1.1.0(1mo ago)0130↓41.7%MITPHP ^8.2

Since Jun 21Compare

[ Source](https://github.com/sashalenz/chatwoot-api)[ Packagist](https://packagist.org/packages/sashalenz/chatwoot-api)[ Docs](https://github.com/sashalenz/chatwoot-api)[ RSS](/packages/sashalenz-chatwoot-api/feed)WikiDiscussions Synced 2w ago

READMEChangelog (4)Dependencies (24)Versions (5)Used By (0)

Chatwoot API for Laravel
========================

[](#chatwoot-api-for-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/a2a491e6d767efa1c868c5c33c407b3041f4a6355937ff95651c79cd2c5ad7f4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f73617368616c656e7a2f63686174776f6f742d6170692e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/sashalenz/chatwoot-api)[![Total Downloads](https://camo.githubusercontent.com/bf9d75a06fb7fd2b8978ca5d6eea6742f53ae709ce968aed867170d5bd1889a6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f73617368616c656e7a2f63686174776f6f742d6170692e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/sashalenz/chatwoot-api)[![License](https://camo.githubusercontent.com/516e360472ad8c731f0f4750ddcb41e7b79fce36bd001e618ab0c921e141296f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f73617368616c656e7a2f63686174776f6f742d6170692e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)

A thin, fluent Laravel SDK for the [Chatwoot](https://www.chatwoot.com/) **Application API**. It wraps contacts, conversations and messages behind a small, expressive API so you can integrate Chatwoot into any Laravel application without hand-rolling HTTP calls.

> **Authentication.** Chatwoot's Application API authenticates with the `api_access_token`header — a user/agent token **or** an agent-bot token — **not** `Authorization: Bearer`. This package handles that for you.

Requirements
------------

[](#requirements)

- PHP `^8.2`
- Laravel `11.x`, `12.x` or `13.x`
- A Chatwoot installation (cloud or self-hosted) and an Application API access token

Installation
------------

[](#installation)

Install the package via Composer:

```
composer require sashalenz/chatwoot-api
```

Optionally publish the config file:

```
php artisan vendor:publish --tag="chatwoot-api-config"
```

Configuration
-------------

[](#configuration)

Set the following variables in your `.env`:

```
CHATWOOT_BASE_URL=https://app.chatwoot.com

# Application API (agent/system side)
CHATWOOT_ACCOUNT_ID=1
CHATWOOT_API_TOKEN=your-api-access-token

# Client API (API-channel inbound bridge)
CHATWOOT_INBOX_IDENTIFIER=your-inbox-identifier
CHATWOOT_HMAC_KEY=your-hmac-key   # optional, only if the inbox enables identity validation

# Platform API (installation provisioning) — only if you use platform* resources
CHATWOOT_PLATFORM_TOKEN=your-platform-app-token
```

KeyEnvDescription`base_url``CHATWOOT_BASE_URL`Base URL of your Chatwoot installation. Do **not** include the `/api/v1` prefix — the transport adds it.`account_id``CHATWOOT_ACCOUNT_ID`Default account id for the **Application API** path. Can be overridden per call.`token``CHATWOOT_API_TOKEN`**Application API** access token sent in the `api_access_token` header. Can be overridden per call.`identifier``CHATWOOT_INBOX_IDENTIFIER`**Client API** inbox identifier (from the API-channel inbox settings). Auth for the public bridge surface — no agent token needed.`hmac_key``CHATWOOT_HMAC_KEY`Optional HMAC key for Client API identity validation.`platform_token``CHATWOOT_PLATFORM_TOKEN`**Platform API** app token. Sent in the same `api_access_token` header, but a different token than the Application one. Can be overridden per call.### Three API families

[](#three-api-families)

- **Application API** (`contacts()`, `conversations()`, `messages()`, …) — the agent/system side. Authenticates with an agent/user **access token** and acts within an account.
- **Client API** (`client()`) — the public **API-channel** surface. Authenticates with the **inbox identifier** (no agent token) and is the canonical path for an integration that pushes a customer's messages *into* Chatwoot as `incoming`.
- **Platform API** (`platformAccounts()`, `platformAgentBots()`, `platformUsers()`) — installation-level provisioning of accounts, users and bots. Authenticates with the **platform app token** and is not account-scoped.

Usage
-----

[](#usage)

The package exposes a static entrypoint, `ChatwootApi`, with one method per resource. Entity methods return typed [`spatie/laravel-data`](https://github.com/spatie/laravel-data)DTOs (see [Typed responses](#typed-responses) below).

```
use Sashalenz\ChatwootApi\ChatwootApi;

// Create a contact. When `inbox_id` is supplied, the returned DTO also carries
// `sourceId` — the stable contact ↔ inbox key.
$contact = ChatwootApi::contacts()->create([
    'name' => 'Jane Doe',
    'phone_number' => '+15551234567',
    'inbox_id' => 1,
    'custom_attributes' => ['plan' => 'pro'],
]);

// Open a conversation for that contact-inbox.
$conversation = ChatwootApi::conversations()->create($contact->sourceId, inboxId: 1);

// Post a message into the conversation.
ChatwootApi::messages()->create(
    conversationId: $conversation->id,
    content: 'Hello there!',
    messageType: 'incoming',
);

// Hand the conversation off to a human agent.
ChatwootApi::conversations()->toggleStatus($conversation->id, 'open');
```

### Typed responses

[](#typed-responses)

Entity methods return DTOs under `Sashalenz\ChatwootApi\Data\*` (e.g. `ContactData`, `ConversationData`, `MessageData`, `InboxData`, …) with idiomatic camelCase properties mapped from Chatwoot's snake\_case payloads. Unknown fields are ignored, so the DTOs tolerate Chatwoot adding keys.

- **Single-entity** methods (`create`, `get`/`show`, `update`) return the entity DTO.
- **List** methods return `Paginated` — a `payload` array of DTOs plus the raw `meta`, with `count()`, `currentPage()` and `totalCount()` helpers.
- **`delete()`** (and `removeMembers`) return `bool`.
- A few **ad-hoc action** endpoints (`toggleStatus`, `assign`, `setCustomAttributes`, `meta`, all of `reports()`, `platformUsers()->login()`) return an `Illuminate\Support\Collection` of the raw response.

```
$page = ChatwootApi::contacts()->list(['page' => 1]);

$page->count();          // items on this page
$page->currentPage();    // 1
$page->totalCount();     // total across all pages (when Chatwoot returns it)

foreach ($page->payload as $contact) {
    echo $contact->name, ' ', $contact->phoneNumber, PHP_EOL;
}
```

### Client API (API-channel inbound bridge)

[](#client-api-api-channel-inbound-bridge)

Push a customer's messages into an API-channel inbox using only the inbox identifier — no agent token. Messages are created as `incoming`.

```
use Sashalenz\ChatwootApi\ChatwootApi;

// 1) Upsert the contact (pass `identifier` to keep it stable across sessions).
$contact = ChatwootApi::client()->createContact([
    'identifier' => 'viber:01234567890A=',
    'name' => 'Petro',
    'custom_attributes' => ['client_id' => 42],
]);
$sourceId = $contact->sourceId;

// 2) Open a conversation, 3) push the incoming message.
$conversation = ChatwootApi::client()->createConversation($sourceId);
ChatwootApi::client()->createMessage($sourceId, $conversation->id, 'Привіт');

// Per-call inbox override + identity hash (when the inbox enables validation):
ChatwootApi::client('other-inbox')->createContact([
    'identifier' => 'viber:xyz',
    'identifier_hash' => ChatwootApi::client()->identifierHash('viber:xyz'),
]);
```

Agent replies flow back to you via the inbox **Webhook URL** (a `message_created`event with `message_type: outgoing`) — handle that in your app and deliver to the transport (see [Handling webhooks](#handling-webhooks)).

### Handling webhooks

[](#handling-webhooks)

Chatwoot POSTs events to your configured Webhook URL. `WebhookEvent` parses the body and exposes the event plus typed accessors for the subject entity:

```
use Sashalenz\ChatwootApi\Data\WebhookEvent;

$event = WebhookEvent::fromArray($request->all()); // or ::fromJson($request->getContent())

if ($event->isMessageCreated() && $event->isOutgoing()) {
    $message = $event->message();           // MessageData
    $conversation = $event->conversation(); // ConversationData|null
    // …deliver $message->content to your transport
}
```

`message()`, `conversation()` and `contact()` return the relevant DTO (or `null`) regardless of which event family arrived; `raw()` exposes the full payload for anything not modelled. `isIncoming()`/`isOutgoing()` normalise the message type across the webhook (string) and REST (integer) forms.

### Per-call account &amp; token overrides

[](#per-call-account--token-overrides)

Useful for multi-account or multi-token setups. Any override wins over the config value:

```
ChatwootApi::messages()
    ->accountId(2)
    ->token($otherToken)
    ->create($conversationId, 'Hi from account 2', 'outgoing');
```

API surface
-----------

[](#api-surface)

ResourceMethodDescription`contacts()``create(array $attributes)`Create a contact.`list(array $query = [])`List contacts.`get(int $contactId)`Fetch a single contact.`update(int $contactId, array $attributes)`Update a contact.`delete(int $contactId)`Delete a contact.`search(string $q, array $query = [])`Free-text search (name/email/phone/identifier).`filter(array $payload)`Advanced contact filtering (query-builder payload).`createInbox(int $contactId, int $inboxId, ?string $sourceId = null)`Associate an existing contact with an inbox and get a `source_id`.`contactableInboxes(int $contactId)`Inboxes the contact can be reached on.`conversations(int $contactId)`List the contact's conversations.`labels(int $contactId)` / `addLabels(int $contactId, array $labels)`List / set the contact's labels.`conversations()``create(string $sourceId, int $inboxId, array $extra = [])`Create a conversation for a contact-inbox.`list(array $filters = [])`List conversations (filters: `status`, `assignee_type`, `inbox_id`, `team_id`, `labels`, `q`, `page`).`show(int $conversationId)`Fetch a single conversation.`update(int $conversationId, array $attributes)`Update a conversation (`priority`, `additional_attributes`, …).`meta(array $query = [])`Conversation counts (mine / unassigned / assigned / all).`filter(array $payload)`Advanced conversation filtering (query-builder payload).`toggleStatus(int $conversationId, string $status)`Set status: `open`, `pending`, `resolved` or `snoozed`.`togglePriority(int $conversationId, string $priority)`Set priority: `urgent`/`high`/`medium`/`low`/`none`.`assign(int $conversationId, ?int $assigneeId, ?int $teamId)`Assign to an agent and/or team.`setCustomAttributes(int $conversationId, array $customAttributes)`Set conversation custom attributes.`labels(int $conversationId)` / `addLabels(int $conversationId, array $labels)`List / set conversation labels.`toggleTyping(int $conversationId, string $typingStatus)`Toggle agent typing indicator (`on`/`off`).`inboxes()``list()` / `get(int $inboxId)`List inboxes / fetch one.`create(array $attributes)` / `update(int $inboxId, array $attributes)`Create / update an inbox.`agentBot(int $inboxId)` / `setAgentBot(int $inboxId, ?int $agentBotId)`Show / assign (or detach) the inbox agent-bot.`members(int $inboxId)`List inbox agent members.`addMembers` / `updateMembers` / `removeMembers (int $inboxId, array $userIds)`Manage inbox agent members.`messages()``create(int $conversationId, string $content, string $messageType = 'incoming', array $extra = [])`Post a message (`incoming` or `outgoing`).`list(int $conversationId, array $query = [])`List messages of a conversation.`delete(int $conversationId, int $messageId)`Delete a message.`agents()``list` / `create` / `update` / `delete`Manage account agents.`agentBots()``list` / `get` / `create` / `update` / `delete`Manage agent bots.`teams()``list` / `get` / `create` / `update` / `delete`Manage teams.`members` / `addMembers` / `updateMembers` / `removeMembers`Manage team agents.`labels()``list` / `get` / `create` / `update` / `delete`Manage the label catalogue.`cannedResponses()``list` / `create` / `update` / `delete`Manage canned responses.`customAttributeDefinitions()``list` / `get` / `create` / `update` / `delete`Manage custom attribute definitions.`customFilters()``list` / `get` / `create` / `update` / `delete`Manage saved custom filters.`account()``get()` / `update(array $attributes)`Read / update the current account.`profile()``get()` / `update(array $profile)`Read / update the token owner's profile.`automationRules()``list` / `get` / `create` / `update` / `delete`Manage automation rules.`webhooks()``list` / `create` / `update` / `delete`Manage account webhooks.`integrations()``apps()` / `createHook` / `updateHook` / `deleteHook`List integration apps and manage hooks.`reports()``account` / `summary` / `conversations` / `firstResponseTimeDistribution` / `inboxLabelMatrix` / `outgoingMessagesCount`Metrics &amp; reports (v2 endpoints).`helpCenter()``listPortals` / `createPortal` / `updatePortal` / `createCategory` / `createArticle`Manage Help Center portals, categories &amp; articles.`platformAccounts()``create` / `get` / `update` / `delete` / `users` / `createUser` / `deleteUser`**Platform API** — provision accounts and account-user links.`platformAgentBots()``list` / `get` / `create` / `update` / `delete`**Platform API** — installation-wide agent bots.`platformUsers()``create` / `get` / `update` / `delete` / `login`**Platform API** — provision users; `login` returns an SSO link.`client()``inbox()`Read inbox info (health check).`createContact(array $attributes)`Upsert a contact → returns `source_id`.`getContact(string $sourceId)`Fetch a contact by `source_id`.`updateContact(string $sourceId, array $attributes)`Update a contact (name / custom attributes).`createConversation(string $sourceId, array $extra = [])`Open a conversation for the contact.`listConversations(string $sourceId)`List the contact's conversations.`getConversation(string $sourceId, int $conversationId)`Fetch one conversation of the contact.`createMessage(string $sourceId, int $conversationId, string $content, array $extra = [])`Push an `incoming` message.`createMessageWithAttachments(string $sourceId, int $conversationId, ?string $content, array $attachments)`Push an `incoming` message with file attachments (multipart).`listMessages(string $sourceId, int $conversationId)`List the messages of a conversation.`updateMessage(string $sourceId, int $conversationId, int $messageId, array $attributes)`Update a message (e.g. CSAT response).`identifierHash(string $contactIdentifier)`HMAC hash for identity validation.See the [Chatwoot Application API reference](https://developers.chatwoot.com/api-reference)for the full set of accepted attributes.

Error handling
--------------

[](#error-handling)

Non-2xx responses and transport failures are wrapped in `Sashalenz\ChatwootApi\Exceptions\ChatwootApiException`. Requests automatically retry transient failures (2 retries, 200 ms apart) with a 15 s timeout.

```
use Sashalenz\ChatwootApi\Exceptions\ChatwootApiException;

try {
    ChatwootApi::contacts()->create(['name' => 'Jane']);
} catch (ChatwootApiException $e) {
    report($e);
}
```

Testing
-------

[](#testing)

```
composer test          # run the test suite (Pest)
composer test-coverage # run with coverage
composer analyse       # static analysis (PHPStan / Larastan)
composer format        # apply code style (Laravel Pint)
composer format-test   # check code style without writing
```

Changelog
---------

[](#changelog)

Please see the commit history for changes.

Contributing
------------

[](#contributing)

Pull requests are welcome. Please make sure `composer test`, `composer analyse`and `composer format-test` pass before submitting.

Security
--------

[](#security)

If you discover a security issue, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Oleksandr Petrovskyi](https://github.com/sashalenz)

License
-------

[](#license)

The MIT License (MIT). Please see the [License File](LICENSE.md) for more information.

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance90

Actively maintained with recent releases

Popularity14

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

4

Last Release

45d ago

Major Versions

0.1.1 → 1.0.02026-06-21

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/13202688?v=4)[Oleksandr Petrovskyi](/maintainers/sashalenz)[@sashalenz](https://github.com/sashalenz)

---

Tags

laravelinboxsashalenzchatwootomnichannelchatwoot-api

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/sashalenz-chatwoot-api/health.svg)

```
[![Health](https://phpackages.com/badges/sashalenz-chatwoot-api/health.svg)](https://phpackages.com/packages/sashalenz-chatwoot-api)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.4M352](/packages/psalm-plugin-laravel)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

817336.8k3](/packages/defstudio-telegraph)[api-platform/laravel

API Platform support for Laravel

58174.6k18](/packages/api-platform-laravel)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

78727.1M206](/packages/laravel-mcp)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5222.6k](/packages/simplestats-io-laravel-client)[propaganistas/laravel-disposable-email

Disposable email validator

6023.2M7](/packages/propaganistas-laravel-disposable-email)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
