MyComm docs
Menu

SDKs

PHP SDK

Install the PHP SDK, send a message, handle errors, and know what it checks before it sends.

mycomm/mycomm-php is the official client for PHP 8.2+. It has a method for every operation of the API, typed arguments and results, retries that cannot double-send, a check of your arguments before a request goes out, and webhook verification.

composer require mycomm/mycomm-php
composer require guzzlehttp/guzzle   # any PSR-18 HTTP client works; Guzzle is used if installed

Send a message#

use MyComm\Client;

$mycomm = new Client(getenv('MYCOMM_API_KEY'));

$message = $mycomm->messages->send(
    to: '+923001234567',
    body: 'Your order #1094 is ready for pickup.',
    category: 'transactional',
    reference_id: 'order-1094',
);

echo $message->id;
echo $message->status->value;   // "queued"  (MessageStatus::Queued)

Every resource of the API reference is a property of the client (messages, contacts, webhookEndpoints, ...) and every operation a method on it. Arguments are named like the API's fields, so the reference and your editor agree; pass them by name.

What it checks before sending#

The limits and rules of the OpenAPI document are checked first, and a mistake fails at once with the field named:

use MyComm\Exceptions\InvalidArgumentException;

try {
    $mycomm->messages->send(to: $number, body: $text, expires_in: 30);
} catch (InvalidArgumentException $e) {
    echo $e->getMessage();   // expires_in must be between 60 and 604800 (got 30).
    $e->field;               // "expires_in"
    $e->rule;                // "OUT_OF_RANGE"
    $e->violations;          // every problem found, not only the first
}

It checks ranges and lengths, allowed values, UUID format, metadata size and types, that you give exactly one of to and contact_id and at least one content field, that variables comes with template_id, and that category comes with the bulk lane. The list is generated from the contract, so it follows the API. What depends on state, such as an opt-out, is answered by the server. If the API relaxes a rule before you update the SDK, create the client with validate: false.

Handle errors#

Every error answer is an exception with the code, status, message, details and request id.

use MyComm\Enums\ErrorCode;
use MyComm\Exceptions\ApiException;

try {
    $mycomm->messages->send(to: $number, body: $text, category: 'marketing');
} catch (ApiException $e) {
    if ($e->is(ErrorCode::RecipientOptedOut)) {
        // do not retry: the recipient unsubscribed
    }
    logger()->warning($e->summary());   // RECIPIENT_OPTED_OUT (422): The recipient ... details: {...}  request_id: ...
    $e->docUrl();                        // the error reference entry for this code
}

$e->code() is the enum case, or null for a code newer than your SDK; $e->errorCode is the same value as text. A validation error lists its fields: ValidationException::fields() and summary(). The exception types by status are in the package README. getMessage() says what happened and what to do; never parse it.

Retries and idempotency#

The SDK retries twice (configurable) after a network error, a 429, a 503 or another 5xx, waiting as long as Retry-After asks (a number of seconds or an HTTP date). Every POST carries an Idempotency-Key, and a retry repeats the same key, so a retried send cannot send twice. Pass your own to make a whole job repeatable:

use MyComm\RequestOptions;

$mycomm->messages->send(
    to: $order->phone,
    body: "Order {$order->number} has shipped.",
    requestOptions: new RequestOptions(idempotencyKey: "order-shipped-{$order->id}", maxRetries: 0),
);

The rules behind this are on Idempotency and retries.

Verify your settings#

$result = $mycomm->verify(to: '+923001234567', lineId: 'LINE_ID');   // lineId may be left out with a key limited to one line

if (! $result->ok()) {
    foreach ($result->problems() as $problem) {
        echo $problem, "\n";
    }
}

verify() checks the key and dry-runs a send to your number. It sends nothing, and it reports a failure as a failed check, not an exception. See Verify your integration.

Webhooks#

use MyComm\Webhooks\Webhook;
use MyComm\Webhooks\Events\MessageDelivered;

$event = Webhook::constructEvent($rawBody, $_SERVER['HTTP_MYCOMM_SIGNATURE'], $secret);   // throws if the signature is wrong

if ($event instanceof MessageDelivered) {
    $event->data->message->id;
}

There is a class for each event in the event catalogue; a type newer than the SDK arrives as UnknownEvent. Verification accepts a rotated secret during the overlap and rejects a timestamp more than 300 seconds off.

Test your own code#

MyComm\Testing\MyCommFake replaces the network: every operation answers with the example of the reference unless you stub it.

$fake = new MyCommFake;
$fake->respond('messages.send', FakeResponse::error(422, 'RECIPIENT_OPTED_OUT'));

$service = new NotifyCustomer($fake->client());
// ... then $fake->assertCalled('messages.send');

The package README has the full reference, the partner API ($mycomm->partner->accounts->provision(...)) and the changelog.