PHP

Install coss/coss with Composer, configure the client, handle errors and verify webhooks in PHP.

The PHP SDK (PHP 8.1+) is coss/coss on Packagist. For Laravel's mailer, use the Laravel driver instead: it sends your mailables unchanged.

composer require coss/coss

It sends requests with any PSR-18 HTTP client the project has, found by php-http/discovery. Without one, add Guzzle: composer require guzzlehttp/guzzle.

<?php

use Coss\Coss;
use Coss\Email\Requests\SendEmailBody;
use Coss\Types\SendEmailRequest;

$client = new Coss(); // reads COSS_API_KEY

$email = $client->email->send(new SendEmailBody([
    'body' => new SendEmailRequest([
        'from' => 'Acme <hello@acme.com>',
        'to' => ['ada@example.com'],
        'subject' => 'Welcome to Acme',
        'html' => '<p>Thanks for signing up!</p>',
    ]),
]));
echo $email->id, ' ', $email->status;

Requests are objects built from arrays whose keys are the API's fields in camelCase (replyTo, scheduledAt).

Options

new Coss(apiKey: …, apiVersion: …, options: [...]):

Every method also takes the same options for that call only.

Errors

A failed request throws Coss\Exceptions\CossApiException: getCode() is the HTTP status and getBody() the API's error envelope, as JSON. A request that never got a response throws Coss\Exceptions\CossException.

use Coss\Exceptions\CossApiException;

try {
    $client->email->get('email_01k7c8m4q2f3e9v6t5r1n0p8yz');
} catch (CossApiException $e) {
    $error = json_decode($e->getBody(), true)['error'];
    echo $e->getCode(), ' ', $error['code'], ' ', $error['request_id'];
}

Idempotency and lists

Requests of endpoints that take an Idempotency-Key have an idempotencyKey field; every other POST gets a random key of its own, reused by its retries.

List methods return one page. Pass the last id as after while hasMore is true:

use Coss\Email\Requests\ListEmailRequest;

$after = null;
do {
    $page = $client->email->list(new ListEmailRequest(['limit' => 100, 'after' => $after]));
    foreach ($page->data as $email) {
        echo $email->id, "\n";
    }
    $after = end($page->data)->id ?? null;
} while ($page->hasMore);

Webhooks

Coss\Webhooks::verify checks a webhook request's signature and age and returns the parsed event (an array); it throws Coss\WebhookVerificationException when you must reject the request. Pass the raw body exactly as received and the headers (getallheaders(), PSR-7's getHeaders() or $_SERVER). Coss\Webhooks::verifyLogDrainBatch does the same for log drains and returns the batch's lines.

use Coss\Webhooks;
use Coss\WebhookVerificationException;

try {
    $event = Webhooks::verify(file_get_contents('php://input'), getallheaders(), getenv('COSS_WEBHOOK_SECRET'));
} catch (WebhookVerificationException) {
    http_response_code(400);
    exit;
}
error_log($event['type']);
http_response_code(204);