Claves API
`keys->list`, `listAll`, `iterate`, `get`, `create`, `update`, `delete`, `rotate` y `revoke`, y los lectores del registro de solicitudes, de la actividad y de las estadísticas.
Todos los métodos
use OpenEmail\Constants\ApiScopes; $key = $client->keys->create([ 'name' => 'Billing sender', 'scopes' => [ApiScopes::EMAILS_SEND], 'domainAllowlist' => ['billing.acme.com'], 'expiresInMinutes' => 60 * 24 * 90,]); file_put_contents('.openemail-billing-key', $key['token']); $client->keys->update($key['id'], ['enabled' => false]); $rotated = $client->keys->rotate($key['id']);file_put_contents('.openemail-billing-key', $rotated['token']); $client->keys->revoke($key['id'], ['reason' => 'Replaced']);$client->keys->delete($key['id']);create y rotate son las únicas llamadas que devuelven un secreto, en token, una vez. Cada lectura devuelve maskedKey en su lugar. update desactiva y activa una clave con enabled, la alternativa reversible a revoke, y delete solo quita una clave que ya se revocó: cualquier otra clave da un 409 not_revoked, lanzado como una ConflictException. Leer necesita keys:read y cada cambio keys:manage.
list devuelve una OpenEmail\Result\Page, listAll devuelve todas las claves en un solo array, e iterate devuelve un Generator que entrega una clave cada vez. create y update aceptan el cuerpo como un solo array con los nombres de la API, y revoke acepta un array opcional con reason. Un token de acceso OAuth llega a estas llamadas solo cuando la persona que conectó la app es la propietaria del espacio de trabajo. El de cualquier otra persona recibe una PermissionException con errorCode igual a owner_only.
El paquete nunca reintenta create ni rotate. Un reintento tras una respuesta perdida crearía una segunda clave, o invalidaría el secreto que devolvió el primer intento. update y revoke se reintentan tras un fallo de red, porque repetirlos deja la misma clave, y delete no.
Nunca más amplia que quien llama
Una clave nunca crea ni alcanza una clave más amplia que ella misma. Ámbitos, rol, caducidad, modo y ámbito de envío tienen que quedar dentro de la clave que llama, o la llamada lanza una PermissionException con errorCode igual a beyond_caller_authority, y param nombra el eje. Una clave acotada a algunos dominios o direcciones solo ve las claves dentro de su propio ámbito de envío. rotate sobre la clave que llama también funciona con keys:write, como $client->me->rotate().
La verificación adicional no puede aplicarse a una llamada hecha con una clave, así que keys:manage es una credencial que crea credenciales. Dala solo a una automatización que emite claves, dale a esa clave un rol, un ámbito de envío y una caducidad, y vigila listWorkspaceActivity, donde todo lo que hace queda registrado a su nombre.
Registro de solicitudes y actividad
$failures = $client->keys->listRequests( '4c1b257a66287fd113bd89d0', failedOnly: true, since: new \DateTimeImmutable('-1 day'),);echo count($failures), PHP_EOL; foreach ($client->keys->iterateWorkspaceActivity() as $change) { echo $change['keyName'], ' ', $change['type'], ' ', $change['actor']['label'] ?? 'system', PHP_EOL;}listRequests y listActivity leen una clave, y listWorkspaceRequests y listWorkspaceActivity leen todas las claves o las que nombra keyIds:, como array o como una sola cadena separada por comas. Cada una tiene al lado un gemelo listAll y otro iterate, como listAllRequests e iterateRequests. Aceptan since: y until: como DateTimeInterface o cadena ISO 8601, y los lectores de solicitudes aceptan además failedOnly:.
stats lee lo que hicieron las claves dentro de una ventana de tiempo: el correo que enviaron y qué fue de él, las llamadas rechazadas, las solicitudes que hicieron y las rutas a las que llamaron. Acepta los mismos keyIds:, since: y until:, más grain: y offsetMinutes:, cubre los 30 días anteriores a ahora cuando no indicas ninguna ventana, y necesita emails:read además de keys:read.
until: tiene que ser posterior a since:, o la llamada lanza una InvalidRequestException con errorCode igual a invalid_parameter y param igual a until. Un DateTimeInterface se envía en UTC, y una cadena se envía tal cual, así que tiene que ser una marca de tiempo ISO 8601 como 2026-09-01T00:00:00Z.