PHP SDK
The official PHP SDK (uchara/uchara-php) for backend integration with the
Uchara Chat Platform. It provides a Server SDK for server-to-server calls
(authenticated with an API key), an Agent SDK for human-agent JWT sessions,
and a Visitor SDK for embedding the chat widget in customer applications.
Requirements
Section titled “Requirements”- PHP
^8.1 - Composer
ext-json- Guzzle
^7.5(installed automatically)
Installation
Section titled “Installation”composer require uchara/uchara-phpNative (non-Laravel) setup
Section titled “Native (non-Laravel) setup”The Uchara factory class provides ergonomic constructors for all three SDKs, plus a
make() helper that builds the appropriate SDK from a configuration array.
<?php
require 'vendor/autoload.php';
use Uchara\SDK\Uchara;
// Server SDK (API key)$server = Uchara::server( apiUrl: 'https://api.uchara.com', apiKey: getenv('UCHARA_API_KEY'),);
// Agent SDK (human-agent JWT)$agent = Uchara::agent( apiUrl: 'https://api.uchara.com',);$agent->login( email: getenv('UCHARA_AGENT_EMAIL'), password: getenv('UCHARA_AGENT_PASSWORD'),);
// Visitor SDK (widget token)$visitor = Uchara::visitor( apiUrl: 'https://api.uchara.com', widgetToken: 'wgt_your_token',);
// Or build from a config array$sdk = Uchara::make([ 'api_url' => 'https://api.uchara.com', 'api_key' => getenv('UCHARA_API_KEY'), 'access_token' => getenv('UCHARA_ACCESS_TOKEN'), 'default' => 'server', // or 'agent' or 'visitor' 'widget_token' => 'wgt_your_token', 'timeout' => 30,]);Laravel setup
Section titled “Laravel setup”The package ships a service provider, a facade, and a config file.
1. Publish the config
Section titled “1. Publish the config”php artisan vendor:publish --tag=uchara-config2. Configure .env
Section titled “2. Configure .env”UCHARA_API_URL=https://api.uchara.comUCHARA_API_KEY=uchara_sk_...UCHARA_ACCESS_TOKEN=agent_access_tokenUCHARA_WIDGET_TOKEN=wgt_your_tokenUCHARA_DEFAULT=serverUCHARA_TIMEOUT=303. Use the facade
Section titled “3. Use the facade”use Uchara\SDK\Laravel\Facades\Uchara;
// The facade forwards to the default SDK, so you can call any SDK method:$members = Uchara::listMembers();
// Or resolve a specific SDK:$server = Uchara::server(); // ServerSDK$agent = Uchara::agent(); // AgentSDK$visitor = Uchara::visitor(); // VisitorSDK$sdk = Uchara::sdk(); // default SDKThe manager is registered as the uchara singleton and caches SDK instances, so
Uchara::listMembers() works out of the box.
Agent SDK
Section titled “Agent SDK”Use the Agent SDK when a message must be shown as the logged-in human agent rather
than as a bot. Login stores the access and refresh tokens in the SDK instance. The
API derives the sender identity from the JWT; sender_type and sender_id should
not be included in message payloads.
use Uchara\SDK\AgentSDK;
$agent = new AgentSDK('https://api.uchara.com');$login = $agent->login( email: getenv('UCHARA_AGENT_EMAIL'), password: getenv('UCHARA_AGENT_PASSWORD'), workspaceSlug: getenv('UCHARA_WORKSPACE_SLUG') ?: null,);
$message = $agent->sendMessage('conv_abc123', [ 'content' => 'Halo, saya siap membantu.',]);
// Exchange the stored refresh token when the access token expires.$agent->refresh();Secure backend-to-browser session (legacy agent-token flow)
Section titled “Secure backend-to-browser session (legacy agent-token flow)”Prefer the one-time dashboard SSO flow described under the Server SDK below for seamless dashboard handoff. This agent-token flow remains supported for existing integrations.
Never expose a Server API key in browser code. Create a short-lived agent session on your backend, then return only that session to your authenticated dashboard:
// Backend only.$server = Uchara::server( apiUrl: 'https://api.uchara.com', apiKey: getenv('UCHARA_API_KEY'),);$session = $server->createAgentSession('agent@example.com');
// Return $session from your own authenticated HTTPS endpoint.In the browser, initialize the Agent SDK with the returned token,
refresh_token, and member values:
const agent = new AgentSDK({ apiURL: 'https://api.uchara.com' });agent.loginWithToken(session);The API key’s workspace must contain an active member with the requested email. The access token is short-lived; rotate it with the refresh token.
Available agent operations include getMe, updateAvailability, conversation and
message methods, assignment/workflow actions, notes, contacts, members, and channels.
Server SDK
Section titled “Server SDK”The ServerSDK authenticates with a Server SDK API key (uchara_sk_...) and
wraps the authenticated /v1/* REST endpoints. All methods return the unwrapped
data payload as a PHP array.
<?php
use Uchara\SDK\Uchara;use Uchara\SDK\UcharaException;
$client = Uchara::server( apiUrl: 'https://api.uchara.com', apiKey: getenv('UCHARA_API_KEY'),);
try { // Send a message (defaults to sender_type 'bot') $message = $client->sendMessage('conv_abc123', [ 'content' => 'Your order has shipped! 🚚', ]);
// List open conversations $conversations = $client->listConversations([ 'status' => 'open', 'limit' => 10, ]);
// Upsert a contact (match by external_id) $contact = $client->upsertContact([ 'external_id' => 'user_123', 'name' => 'John Doe', 'email' => 'john@example.com', ]);} catch (UcharaException $e) { echo "Error ({$e->getStatus()}): {$e->getMessage()}\n"; print_r($e->getDetails());}Identity & workspace
Section titled “Identity & workspace”$client->getMe(): array$client->updateMe(array $data): array$client->listMyWorkspaces(): array$client->updateMyAvailability(string $availability): array$client->getWorkspace(): arrayContacts
Section titled “Contacts”$client->upsertContact(array $data): array$client->getContact(string $contactId): array$client->listContacts(array $options = []): arrayConversations
Section titled “Conversations”$client->getConversation(string $conversationId): array$client->listConversations(array $filters = []): array$client->assignConversation(string $conversationId, ?string $agentId): array$client->resolveConversation(string $conversationId): array$client->updateConversation(string $conversationId, array $data): array$client->takeoverConversation(string $conversationId): array$client->joinConversation(string $conversationId): array$client->leaveConversation(string $conversationId): array$client->inviteToConversation(string $conversationId, array $data): array$client->listConversationNotes(string $conversationId): array$client->addConversationNote(string $conversationId, array $data): arrayMessages
Section titled “Messages”$client->sendMessage(string $conversationId, array $data): array$client->getMessages(string $conversationId, array $options = []): array
// Aliases$client->sendMessageToConversation(string $conversationId, array $data): array$client->listMessages(string $conversationId, array $options = []): array$client->getConversationMessages(string $conversationId, array $options = []): arrayChannels
Section titled “Channels”$client->listChannels(): array$client->getChannel(string $channelId): array$client->createChannel(array $data): array$client->updateChannel(string $channelId, array $data): array$client->deleteChannel(string $channelId): array$client->setupChannelWebhook(string $channelId, array $data = []): array$client->testChannelConnection(string $channelId, array $data = []): arrayMembers (human workspace users)
Section titled “Members (human workspace users)”Members are the human users of a workspace. Because many users refer to them as
“agents”, ergonomic aliases (listAgents / getAgent / createAgent / …) are
provided alongside the canonical member methods.
$client->listMembers(array $query = []): array$client->getMember(string $memberId): array$client->createMember(array $payload, ?string $idempotencyKey = null): array$client->updateMember(string $memberId, array $payload): array$client->updateMemberRole(string $memberId, string $role): array$client->deactivateMember(string $memberId): array$client->reactivateMember(string $memberId): array$client->deleteMember(string $memberId): arrayDirect provisioning without registration
Section titled “Direct provisioning without registration”Members (human agents) can be provisioned directly via the Server SDK — no
email/password registration is required. This endpoint is restricted to Server
SDK API keys (not ordinary JWTs). Pass an optional Idempotency-Key header so
retries do not create duplicate members:
$member = $client->createMember( ['email' => 'agent@company.com', 'name' => 'Agent One', 'role' => 'agent'], idempotencyKey: 'provision-2024-0001',);Agent aliases
Section titled “Agent aliases”$client->listAgents(array $query = []): array$client->getAgent(string $agentId): array$client->createAgent(array $payload, ?string $idempotencyKey = null): array$client->updateAgent(string $agentId, array $payload): array$client->updateAgentRole(string $agentId, string $role): array$client->deactivateAgent(string $agentId): array$client->reactivateAgent(string $agentId): array$client->deleteAgent(string $agentId): array$client->inviteAgent(array $payload): arrayInvites
Section titled “Invites”$client->inviteMember(array $payload): array$client->listInvites(): array$client->revokeInvite(string $inviteId): arrayBots are a separate resource from human members/agents. Manage them with the dedicated bot methods:
$client->listBots(): array$client->createBot(array $data): array$client->updateBot(string $botId, array $data): array$client->deleteBot(string $botId): arrayCanned responses
Section titled “Canned responses”$client->listCannedResponses(): array$client->createCannedResponse(array $data): array$client->updateCannedResponse(string $id, array $data): array$client->deleteCannedResponse(string $id): arrayAPI keys
Section titled “API keys”$client->createApiKey(array $data): array$client->listApiKeys(): array$client->revokeApiKey(string $keyId): voidSecurity: The raw key value is returned only once, in the
createApiKeyresponse, and cannot be retrieved again later. Store it immediately and treat it as a secret — never commit it to git.
One-time dashboard SSO
Section titled “One-time dashboard SSO”For a seamless handoff from your own authenticated backend to the Uchara
dashboard, issue a one-time SSO ticket with the Server SDK and return the
resulting redirect_url to the browser. The API key stays on your backend; the
browser only ever sees an opaque, short-lived ticket in the URL fragment.
There is no dedicated SDK helper for this — use the underlying HTTP client via
ServerSDK::http()->post(...):
<?php
use Uchara\SDK\Uchara;
// Backend only — UCHARA_API_KEY must remain server-side.$server = Uchara::server( apiUrl: 'https://api.uchara.com', apiKey: getenv('UCHARA_API_KEY'),);
// Issue a one-time ticket for the target member (optional channel scope).$result = $server->http()->post('/v1/auth/sso/ticket', [ 'email' => 'agent@company.com', // 'channel_ids' => ['<channel-uuid>'], // optional; omitted = full workspace]);
// Return $result['redirect_url'] from your own authenticated HTTPS endpoint.// The browser opens it; the dashboard bootstrap exchanges the ticket and// strips it from the URL.$redirectUrl = $result['redirect_url'];Security guidance:
- Keep the API key backend-only — never expose it in browser code.
- Do not log, store, or reuse
redirect_urlvalues. - The ticket is short-lived (60 seconds), one-time, and consumed atomically on exchange; only its hash is stored server-side.
- No JWT, API key, or refresh token ever appears in the URL.
Visitor SDK
Section titled “Visitor SDK”The VisitorSDK wraps the public /v1/widget/* REST endpoints for embedding the
chat widget in customer applications. Call init() first to create a visitor
session and obtain a visitor JWT; subsequent authenticated calls use that token.
<?php
use Uchara\SDK\Uchara;
$visitor = Uchara::visitor( apiUrl: 'https://api.uchara.com', widgetToken: 'wgt_your_token',);
// Create a visitor session (optional identity fields)$session = $visitor->init([ 'external_id' => 'user_123', 'name' => 'Jane Doe', 'email' => 'jane@example.com', 'phone' => '+6281234567890',]);
// Public widget configuration$config = $visitor->getConfig();
// Active conversation, or null when none exists$active = $visitor->getActiveConversation();
// Start a conversation$conv = $visitor->startConversation(['message' => 'Hello!']);
// Messages (limit/offset pagination)$messages = $visitor->getMessages($conv['id'], ['limit' => 50, 'offset' => 0]);
// Send a message as the visitor$visitor->sendMessage($conv['id'], ['content' => 'Thanks!']);
// Upload a file (multipart/form-data)$visitor->upload($conv['id'], '/path/to/receipt.pdf');
// Download the transcript as plain text$text = $visitor->download($conv['id']);
// Close the conversation$visitor->close($conv['id']); // or closeConversation()VisitorSDK methods
Section titled “VisitorSDK methods”$visitor->init(array $contact = []): array$visitor->getConfig(): array$visitor->getActiveConversation(): ?array$visitor->startConversation(array $payload = []): array$visitor->getMessages(string $conversationId, array $options = []): array$visitor->sendMessage(string $conversationId, array $payload): array$visitor->upload(string $conversationId, string $filePath, ?string $filename = null, ?string $mimeType = null): array$visitor->download(string $conversationId): string$visitor->close(string $conversationId): array$visitor->closeConversation(string $conversationId): array$visitor->getVisitorToken(): ?string$visitor->getContactId(): ?stringError handling
Section titled “Error handling”The SDK throws a structured UcharaException on transport errors and non-2xx
responses. It exposes the HTTP status code through both the standard getCode()
and the more explicit getStatus() alias, plus the parsed error payload and the
full structured response.
use Uchara\SDK\UcharaException;
try { $client->sendMessage('conv_abc123', ['content' => 'Hello']);} catch (UcharaException $e) { echo "Status: {$e->getStatus()}\n"; // HTTP status code echo "Message: {$e->getMessage()}\n"; print_r($e->getDetails()); // parsed error payload from the API $response = $e->getResponse(); // ?UcharaResponse for advanced inspection}UcharaResponse
Section titled “UcharaResponse”For advanced callers, ServerSDK::http()->request(...) returns a full
UcharaResponse exposing the status, unwrapped data, pagination meta,
headers, and raw body:
$response = $client->http()->request('GET', '/v1/conversations', ['query' => ['limit' => 10]]);$response->status(); // int$response->data(); // array (unwrapped data payload)$response->meta(); // array (pagination / metadata envelope)$response->headers(); // array$response->rawBody(); // ?string$response->successful(); // boolAPI key security
Section titled “API key security”- The Server SDK API key (
uchara_sk_...) is a secret — load it from an environment variable, never hardcode or commit it. - The raw key value is returned only once when created; store it immediately.
- Keys can be revoked instantly via
revokeApiKey. - The Visitor SDK uses a public widget token, which is safe to embed in client-side code.