walinko / sdk
Official PHP SDK for the Walinko public API.
Requires
- php: >=8.1
- php-http/discovery: ^1.19
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.0 || ^2.0
- psr/log: ^2.0 || ^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.59
- nyholm/psr7: ^1.8
- phpstan/phpstan: ^1.11
- phpunit/phpunit: ^10.5
- symfony/http-client: ^6.4 || ^7.0
This package is auto-updated.
Last update: 2026-05-04 08:36:28 UTC
README
Official PHP client for the Walinko public API.
Send transactional WhatsApp messages from PHP with idempotent retries, structured errors, and a tiny dependency footprint (PSR-18 HTTP).
- PHP 8.1+
- PSR-18 HTTP, PSR-17 factories, PSR-3 logging — bring your own
Guzzle/Symfony/whatever, or let
php-http/discoveryfind one - MIT licensed
Install
composer require walinko/sdk
If your project doesn't already pull in a PSR-18 client (e.g. via
Guzzle, Symfony HTTP Client, or php-http/curl-client), add one too:
composer require symfony/http-client nyholm/psr7
Quick start
use Walinko\Client; $client = new Client([ 'api_key' => getenv('WALINKO_API_KEY'), 'base_url' => 'https://api.walinko.com', // optional 'timeout' => 30, // optional, seconds (used by waitUntilDone) 'max_retries' => 2, // optional // 'http_client' => $psr18Client, // optional // 'request_factory' => $psr17Factory, // optional // 'stream_factory' => $psr17Factory, // optional // 'logger' => $psrLogger, // optional ]); // Sync send — blocks until the message is delivered (or 504 timeout). $result = $client->messages->send([ 'device_id' => 1, 'template_id' => 12, 'variant_index' => 0, // optional, null = primary 'phone' => '+8801617738431', 'variables' => ['name' => 'Kazi', 'dist' => 'Dhaka'], ]); echo $result->trackingId; // tx_... echo $result->waMessageId; // 3EB0... echo $result->status; // "sent" // Async enqueue + poll. $job = $client->messages->enqueue([ 'device_id' => 1, 'template_id' => 12, 'phone' => '+8801617738431', 'variables' => ['name' => 'Kazi', 'dist' => 'Dhaka'], ]); $final = $client->messages->waitUntilDone($job->trackingId, timeout: 60); echo $final->status; // "sent" | "failed"
Looking up a delivery
$status = $client->messages->fetch('tx_767fd2faca0f4037b2a2bbcb91e5735f'); $status->isSent(); // bool $status->errorCode; // null if sent, e.g. "phone_not_on_whatsapp" on failure $status->waMessageId; // WhatsApp's id, set on success $status->createdAt; // DateTimeImmutable $status->sentAt; // DateTimeImmutable, null while pending
Errors
Every exception extends Walinko\Exception\WalinkoException. See
docs/error-codes.md for the full mapping.
use Walinko\Exception; try { $client->messages->send([...]); } catch (Exception\RateLimitException $e) { sleep($e->retryAfter ?? 1); // retry } catch (Exception\ValidationException $e) { $logger->warning('validation failed', ['fields' => $e->fields()]); } catch (Exception\DeviceDisconnectedException) { // tell the user to reconnect their device from the dashboard } catch (Exception\WalinkoException $e) { $logger->error('Walinko send failed', ['error' => $e->getMessage()]); }
Retries
The SDK auto-retries idempotently on:
| Trigger | Behaviour |
|---|---|
| Network errors | Exponential backoff with jitter |
| HTTP 429 | Honours Retry-After (capped at 60s) |
| HTTP 500/502/503/504 | Exponential backoff with jitter |
max_retries (default 2) controls how many additional attempts are made.
4xx responses (other than 429) are surfaced immediately — the request is
malformed or the server has rejected it on application grounds, and no
amount of retrying will help.
Idempotency
The SDK auto-generates a UUID Idempotency-Key for every send /
enqueue call so retries are safe end-to-end. Pass idempotency_key
in the args to set your own (e.g. tying a send to your domain object).
The same key is reused on every retry within a single call.
Rate limits
The server enforces 30 req/min/key (sliding window). The SDK exposes the latest known window state via:
$client->lastRateLimit(); // ?Walinko\Result\RateLimitSnapshot $client->lastRequestId(); // ?string — handy for support tickets
Development
cd sdks/php
composer install
vendor/bin/phpunit
vendor/bin/phpstan analyse
vendor/bin/php-cs-fixer fix --dry-run --diff