Skip to the documentation
PHP

Helpers and constants

What else the package defines besides the client’s methods.

Static methods

MethodWhat it is
OpenEmail::init(), OpenEmail::getClient()Configure the shared client once, then reach it from anywhere. getClient() builds one from the environment if init never ran.
OpenEmail::resetClient()Drops the shared client, so the next getClient() builds a fresh one, which is what a test wants between cases.
new OpenEmail(), OpenEmail::createClient()A separate client. Both read the environment for anything you leave out.
OpenEmail::createTempMail()A disposable-inbox client that carries no API key.
OpenEmail::verifyWebhookSignature()Checks a delivery’s signature in constant time, with a five minute replay window that toleranceSeconds: changes. Returns the decoded event, and throws WebhookSignatureException on any failure.
OpenEmail::toBase64()Base64 for attachment bytes, from a string, a stream resource, an SplFileInfo or a PSR-7 stream.
OpenEmail::isApiKey()Whether a value has the oe_live_ or oe_test_ shape. A shape check, not proof the key still works.
OpenEmail::isAccessToken()Whether a value has the shape of an OAuth access token: 1 to 512 characters, not beginning oe_.
OpenEmail::isSealed()Whether a message’s body is ciphertext. It is false for the two signed formats, whose bodies arrived in the clear.
OpenEmail::resolveLanguage(), OpenEmail::languageByCode(), OpenEmail::isRtlLanguage()The lookups a language picker needs, over the bundled Languages::ALL table.
$client->close()Releases the client’s cURL handle and the connection behind it. A client that is no longer referenced does the same when PHP frees it.

Constants

Every value set the TypeScript SDK exports is a final class in OpenEmail\Constants, with one constant per member under the same names, so WebhookEvents::EMAIL_DELIVERED is email.delivered. values() returns the whole set, which is also how to check a value that came from outside.

constants.php
use OpenEmail\Constants\ApiScopes;use OpenEmail\Constants\PageLimits;use OpenEmail\Constants\WebhookEvents; $events = WebhookEvents::values(); $scopes = [ApiScopes::EMAILS_SEND, ApiScopes::THREADS_READ]; $known = in_array('email.delivered', $events, true); echo count($events), ' ', implode(',', $scopes), ' ', PageLimits::MAX_LIMIT, ' ', $known ? 'known' : 'unknown', PHP_EOL;
ConstantWhat it holds
OpenEmail::VERSIONThe package version.
ApiScopesThe scope vocabulary, for a key-creation screen.
WebhookEvents, WebhookSignatureHeadersThe events an endpoint can subscribe to, and the names of the headers a delivery carries.
ErrorTypesThe error vocabulary that ApiException::$type takes.
PageLimitsThe largest and the default limit: on most paged lists, MAX_LIMIT and DEFAULT_LIMIT: 100 and 25. A few lists take more, and each method’s reference says so.
RuleFields, RuleOperators, RuleActionsThe vocabulary a rule’s conditions and actions are built from.
MessageEncryptionFormatsThe five envelopes ingest can name. Three of them are sealed.
CredentialKinds, StepUpMethods, StepUpErrorCodesWhich credential me->get and me->ping describe, how a verification code is checked, and the codes a verification can fail with.
ThreadSorts, PeopleSorts, FileSorts and the other *SortsThe orders a list can be sorted in.
FormStatuses, BroadcastStatuses, SuppressionReasons and the other setsThe values a field of a resource can take. Each set is named after what it holds.
Languages::ALLEvery language a translated send or preview accepts, with its code, its names and its direction.

Objects

A response is the decoded JSON as an associative array. The package builds an object of its own only where it shapes the answer, and each lives in OpenEmail\Result, is immutable, and is IteratorAggregate and Countable over its rows.

ClassWhat it carries
Pageitems, hasMore and nextCursor, from every paged list.
PeoplePageThe same plus seen, from contacts->listPeople.
TempMessagesPageThe same plus expiresAt, from tempMail->listMessages.
AddressBookPage, AddressBookunrestricted, addresses and domains, from addresses->list (with hasMore and nextCursor) and addresses->listAll.
BatchResultitems, sent and failed, from emails->sendBatch.
TemplateSendsitems, total, page and pageSize, from templates->listSends.
OpenEmail\Http\HttpRequest, OpenEmail\Http\HttpResponseWhat an httpClient: receives and returns. var_dump(), print_r() and json_encode() show a request’s Authorization header as [redacted], while var_export() and Symfony’s dump() show it as it is.

Every exception the package throws implements OpenEmail\Exception\OpenEmailException: ApiException and its subclasses, NetworkException, WebhookSignatureException and InvalidArgumentException, which is thrown for a mistake in the call itself rather than something the API said.

An endpoint this does not wrap yet

A package release should never be what stands between you and an endpoint that already works. $client->raw->request() takes a path and named arguments and returns the decoded body, with the client’s credential, base URL, timeout and retry policy applied.

escape_hatch.php
$result = $client->raw->request(    '/labels',    method: 'POST',    query: ['dryRun' => true],    body: ['name' => 'Invoices'],    repeatable: true,); var_dump($result);

A GET is retried like any other read. Any other method is sent once unless you pass repeatable: true, which is your assertion that it may be sent twice. query: skips values that are null or empty, and apiKey: works as it does on every other method.

What it deliberately does not do

  • It validates no request body. The server’s schema is the only copy of the rules, and a second copy here would eventually refuse an address a newer server accepts, in a version somebody pinned two years ago.
  • It has no runtime dependencies beyond the curl and json extensions. A PSR-18 client is an option, never a requirement.
  • It reshapes a response in one way only: a collection’s data array is lifted out of its envelope into one of the objects above. Every other response comes back as the API sent it, with the API’s camelCase keys.

The package’s parity check keeps this honest. It fails the build when a TypeScript method has no PHP twin, takes different arguments, or sends a different request.