---
title: "Changelog"
description: "Every release of the package, newest first."
url: "https://openemail.uk/docs/php/changelog"
area: "PHP"
category: "Reference"
---

# Changelog

Every release of the package, newest first.

## 0.0.1

The first release. It covers the whole TypeScript SDK as it stood when this release was cut: 430 methods in 41 namespaces, each under its TypeScript name, and every one of them sends byte for byte the request its TypeScript twin sends.

- `OpenEmail\OpenEmail` has a property for every namespace, from `emails`, `threads` and `templates` to `providerImports`, `dnsConnections` and `account`, and the methods on each keep their TypeScript names.
- A request body is an associative array whose keys keep the API’s camelCase names, and options are named arguments such as `idempotencyKey:` and `apiKey:`. A response comes back as the decoded associative array.
- Every paginated resource has `list`, which returns one `Page`, `listAll`, which returns every item as an array, and `iterate`, which returns a Generator that fetches the next page only when it gets there. `PeoplePage`, `TempMessagesPage`, `AddressBookPage`, `AddressBook`, `BatchResult` and `TemplateSends` carry the answers that hold more than a list.
- An API refusal throws `ApiException` or its subclass for the error type, with `status`, `type`, `errorCode`, `param`, `docUrl`, `requestId`, `retryAfterSeconds`, `fields` and `body`, and methods such as `isValidation()` and `isStepUpRequired()`. No response at all throws `NetworkException`, with `isTimeout()` when the deadline passed. A mistake in the call itself throws `InvalidArgumentException` before anything is sent. Every one implements `OpenEmailException`.
- `new OpenEmail()` and `OpenEmail::createClient()` read `OPENEMAIL_API_KEY`, `OPENEMAIL_ACCESS_TOKEN` and `OPENEMAIL_BASE_URL` for anything you leave out, and `OpenEmail::init()`, `OpenEmail::getClient()` and `OpenEmail::resetClient()` manage one shared client. `OpenEmail::createTempMail()` opens disposable inboxes with no credential.
- `accessToken:` takes an OAuth access token, or a callable that returns one, called before every request. Every method takes `apiKey:` to act with another key for one call, and the `tempMail` methods take `inboxToken:`. Every parameter that carries a credential is marked `#[\SensitiveParameter]`.
- `OpenEmail::verifyWebhookSignature()` checks a delivery in constant time, refuses one more than five minutes old and returns the decoded event. It reads the signature from an array of headers in any case, from `$_SERVER`, from a Symfony or Laravel header bag, or from a PSR-7 request.
- `OpenEmail::toBase64()`, `isApiKey()`, `isAccessToken()`, `isSealed()`, `resolveLanguage()`, `languageByCode()` and `isRtlLanguage()` are the helpers of the TypeScript SDK, and every value set its package root exports is a class in `OpenEmail\Constants`.
- It needs PHP 8.2 or later with the curl and json extensions, and nothing else. Requests go through one cURL handle per client, which keeps its connection open between requests and opens a new one after `pcntl_fork`, and `timeout:` bounds a whole attempt. `Psr18HttpClient` sends them through Guzzle, Symfony HttpClient or any other PSR-18 client instead.
- Reads, sends and every write that is safe to repeat are retried on 408, 500, 502, 503 and 504 with backoff, and on a 429 only when its `Retry-After` is a minute or less. Every send carries an idempotency key that its retries reuse.
- The client refuses to send a credential over plain `http:` to anything but this machine, refuses a base URL on `0.0.0.0`, refuses a header that would split a request, and never lets `raw->request()` leave the base URL’s origin.
