# PHP

One POST with cURL or Guzzle, and where to keep the key.

There is no emails.sh PHP package to install: the API is a single JSON POST, and the ext-curl that ships with every PHP build covers it. If your project already has Guzzle, the second example is shorter.

### With cURL

src/Email.php:
```php
<?php
// src/Email.php
// The key comes from https://emails.sh/dashboard/api-keys and is read from the
// environment. Put it in .env and load it however your app already does.

function send_email(string $to, string $subject, string $html): string
{
    $payload = json_encode([
        'from' => 'Acme <hello@acme.com>',
        'to' => [$to],
        'subject' => $subject,
        'html' => $html,
    ], JSON_THROW_ON_ERROR);

    $ch = curl_init('https://emails.sh/v1/emails');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $payload,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 10,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . getenv('EMAILSSH_API_KEY'),
            'Content-Type: application/json',
        ],
    ]);

    $body = curl_exec($ch);
    if ($body === false) {
        throw new RuntimeException('emails.sh unreachable: ' . curl_error($ch));
    }
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);

    $result = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
    if ($status >= 400) {
        $refusal = $result['error'];
        throw new RuntimeException($refusal['code'] . ': ' . $refusal['message'] . ' ' . ($refusal['next'] ?? ''));
    }

    return $result['id'];
}
```

send.php:
```php
<?php
require __DIR__ . '/src/Email.php';

$id = send_email('ada@example.com', 'Your receipt from Acme', '<p>Thanks for your order.</p>');
echo "queued {$id}\n";
```

### With Guzzle

If it is not already there:
```bash
composer require guzzlehttp/guzzle
```

send.php with Guzzle:
```php
<?php
require __DIR__ . '/vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;

$client = new Client(['base_uri' => 'https://emails.sh', 'timeout' => 10]);

try {
    $response = $client->post('/v1/emails', [
        'headers' => ['Authorization' => 'Bearer ' . getenv('EMAILSSH_API_KEY')],
        'json' => [
            'from' => 'Acme <hello@acme.com>',
            'to' => ['ada@example.com'],
            'subject' => 'Your receipt from Acme',
            'html' => '<p>Thanks for your order.</p>',
        ],
    ]);

    $result = json_decode((string) $response->getBody(), true);
    echo "queued {$result['id']}\n";
} catch (ClientException $e) {
    $refusal = json_decode((string) $e->getResponse()->getBody(), true)['error'];
    // next says what to do about it, so log it rather than the class name.
    fwrite(STDERR, $refusal['code'] . ': ' . $refusal['message'] . ' ' . ($refusal['next'] ?? '') . "\n");
}
```

Inside a Laravel application, use the mail driver instead: /docs/laravel.

---

Base URL: https://emails.sh/v1. Auth: `Authorization: Bearer esh_...`.
Whole API in one file: https://emails.sh/llms.txt. All documentation: https://emails.sh/docs.md.
