chatbridge / php-sdk
Framework-neutral PHP SDK for the ChatBridge backend integration API.
Requires
- php: ^8.2
- ext-json: *
- guzzlehttp/guzzle: ^7.8
Requires (Dev)
- illuminate/support: ^11.0|^12.0
- orchestra/testbench: ^9.0|^10.0
- phpunit/phpunit: ^11.0
Suggests
- illuminate/support: Required only for Laravel service-provider integration.
README
Small framework-neutral PHP 8.2 SDK for ChatBridge's backend integration API. It uses dedicated tenant-bound integration credentials; never provide tenant JWTs or X-ChatBridge-Gateway-Token values.
The SDK accepts HTTPS URLs and exact loopback HTTP URLs only. Applications should allow loopback HTTP only in their local environment and enforce HTTPS for production and for any unexpected environment value.
Install
composer require chatbridge/php-sdk
Stable Packagist releases are created from semantic Git tags. Until the first tag is published, Packagist can expose only the development branch; consumers should use a tagged release for production.
Usage
use ChatBridge\Sdk\ClientFactory; use ChatBridge\Sdk\Config\ClientConfig; use ChatBridge\Sdk\Idempotency\IdempotencyKey; use ChatBridge\Sdk\Messages\Message; use ChatBridge\Sdk\Recipients\ExternalContactRecipient; $client = (new ClientFactory)->make(new ClientConfig( baseUrl: 'https://chatbridge.example', clientId: 'cbic_01J00000000000000000000000', clientSecret: 'cbis_REPLACE_WITH_ONE_TIME_SECRET', webhookSecrets: ['cbwh_REPLACE_WITH_WEBHOOK_SECRET'], )); $contact = $client->contacts()->upsert( externalKey: 'example-app:lead:123', accountId: '2', phoneE164: '+60123456789', displayName: 'Aminah Ismail', ); $key = IdempotencyKey::fromParts( 'example-app', 'production', 'agency', '42', 'lead', '123', 'suggestion', '9001', 'send-v1', ); $sent = $client->messages()->send( accountId: '2', recipient: new ExternalContactRecipient('example-app:lead:123'), message: Message::text('Hello'), idempotencyKey: $key, externalReference: 'example-app:lead:123:suggestion:9001', ); $conversation = $client->conversations()->get($sent->conversationId);
Webhook verification
Verify the exact raw body before parsing or trusting tenant/account data. Persist the returned event ID with a unique constraint in the consuming application.
$event = $client->webhooks()->verifyAndParse( payload: $request->getContent(), signature: (string) $request->header('X-ChatBridge-Signature'), timestamp: (string) $request->header('X-ChatBridge-Timestamp'), eventId: $request->header('X-ChatBridge-Event-Id'), eventType: $request->header('X-ChatBridge-Event-Type'), webhookVersion: $request->header('X-ChatBridge-Webhook-Version'), );
Signature verification does not persist replay state. The receiver must store event.id and a SHA-256 payload hash atomically: identical duplicates return success; a reused ID with a different hash is a conflict.
Laravel
The package auto-discovers ChatBridgeServiceProvider. It always binds ClientFactory; a default Client is bound only when CHATBRIDGE_BASE_URL, CHATBRIDGE_CLIENT_ID, and CHATBRIDGE_CLIENT_SECRET are all configured. Multi-agency applications should resolve encrypted credentials from an explicit local connection and use ClientFactory rather than a global client.
Publish configuration with:
php artisan vendor:publish --tag=chatbridge-config
The SDK retries transient transport errors and HTTP 408, 425, 429, 500, 502, 503, and 504 responses up to three attempts. Every retry keeps the method, body, and idempotency key while generating a fresh timestamp and nonce.
Subscription enforcement
Installing this MIT-licensed SDK does not grant access to the hosted ChatBridge service. Every Integration API request is bound to the integration client's ChatBridge tenant and requires an active subscription in addition to valid credentials, scopes, permitted WhatsApp accounts, quota, and rate-limit capacity.
ChatBridge returns HTTP 403 with subscription_required when the client-bound tenant is unpaid or expired. The SDK exposes this as ChatBridge\Sdk\Exceptions\SubscriptionRequiredException. Renewing the tenant subscription restores access without replacing an otherwise active integration credential.
Releases and Packagist
Releases use semantic Git tags such as v1.0.0. Packagist derives package versions from those tags, so this package deliberately does not declare a hard-coded version in composer.json.
Repository CI validates Composer metadata and runs the SDK tests for supported PHP versions. Before tagging a release, deploy any backward-compatible ChatBridge server endpoint that the SDK release requires, then update the changelog and wait for CI to pass.
Packagist synchronization is configured outside this repository because the Packagist API token must never be committed. See docs/releasing.md for the GitHub integration and manual webhook settings.