---
title: "Install"
description: "One Composer package, PHP 8.2 and up, with the curl and json extensions."
url: "https://openemail.uk/docs/php/install"
area: "PHP"
category: "Getting started"
---

# Install

One Composer package, PHP 8.2 and up, with the curl and json extensions.

## Install

> The current release is `0.0.1`. It has a method for every method of the TypeScript SDK, under the same name, and the package’s parity check fails the build when one goes missing or sends a different request.

**Install**

_Composer_

```bash
composer require openemail/sdk
```

**send_email.php**

```
<?php

use OpenEmail\OpenEmail;

require __DIR__ . '/vendor/autoload.php';

$client = new OpenEmail();

$email = $client->emails->send([
    'from' => 'Acme Billing <billing@acme.com>',
    'to' => 'ada@example.com',
    'subject' => 'Your September invoice',
    'html' => '<p>Invoice attached.</p>',
]);

echo $email['id'], ' ', $email['status'], PHP_EOL;
```

`new OpenEmail()` reads the key from `OPENEMAIL_API_KEY`, so the code holds no credential. Pass `apiKey:` when your configuration lives somewhere else. To reach one client from anywhere, configure it once with `OpenEmail::init()` and fetch it with `OpenEmail::getClient()`.

A response is the decoded JSON as an associative array, so `$email['id']` reads the id. The keys keep the API’s names, and so do the methods and their named arguments, which is why `scheduledAt` and `idempotencyKey:` are written the same way here as in the API reference.

> `send` returning does not mean the message has gone. A scheduled or cancellable send comes back `queued` or `scheduled` and settles later. Read `status`, not the fact that the call returned.

## Where it runs

PHP 8.2 and up, with the curl and json extensions that almost every build ships with, and no other dependency. Requests go through one cURL handle per client, so a second request to the API reuses the connection the first one opened, and cURL decodes a compressed response for you.

It works under PHP-FPM, Apache, the command line and long-running workers such as a queue worker, RoadRunner or FrankenPHP. Under PHP-FPM every request starts fresh, so build the client once per request. In a long-running process, keep one for the life of the process. After `pcntl_fork` the child opens a connection of its own rather than reusing the parent’s.

> The client carries a workspace API key that can send mail and read the mailbox, so it belongs on a server, in a job or in a tool that runs on your own machine. Keep the key in an environment variable or your framework’s secrets, never in code.
