Kalo te dokumentacioni
Python

openemail.me

Çdo metodë në këtë hapësirë emrash: nënshkrimi, parametrat, çfarë kthen dhe një shembull.

Metodat

The API key or OAuth access token behind the client: its mode, scopes, role ceiling and workspace.

me.get()

Describe the API key or access token making the call

Pa leje
Nënshkrimi
def get(*, api_key: str | None = None, timeout: float | None = None) -> KeyResource

Returns what the key is: its id, whether it is a live or test key, the workspace it belongs to, the scopes it can use and the allowlists that narrow who it may send as. It needs no scope, because a key may always describe itself, so it works with any valid key and is the first call to make when a request is refused.

scopes is the effective list and the only one that authorises anything. It is the scopes the key was created with intersected with the permissions of the role it was issued under, resolved on every request rather than frozen into the key. grantedScopes is what the key was created holding and roleId names the role that capped it, so a scope present in grantedScopes and missing from scopes was removed by that role. A 403 insufficient_scope on a key the console shows as holding the scope is almost always this, and the fix is to change the role rather than to mint another key.

A key can be narrowed by whole domains, by individual addresses, or by both. domainAllowlist holds whole domains, and the key may send as any address on one of them, including addresses created after the key was. addressAllowlist holds individual addresses and covers only those. Both None means the key may send as any address the workspace owns. When either is set the key is narrowed, and reads of sent mail, tracking and calendar narrow to the same set. An address whose domain is already in domainAllowlist is dropped from addressAllowlist when the key is saved, so the two lists never overlap.

Called with an OAuth access token it describes the token instead, and object tells the two apart. A key answers with object set to 'api_key' and kind set to 'apiKey'. A token answers with object set to 'oauth_token' and kind set to 'oauth', with id and roleId set to None, clientId naming the connected app and mode always 'live'. scopes and grantedScopes are the permissions the person approved for the app, and the allowlists are the addresses and domains the app may reach. expiresAt is when that approval runs out, or None when it never does. It is not the expiry of the access token, which the app renews with its refresh token.

Parametrat

api_keystr

Describes this key instead of the credential the client was built with.

timeoutfloat

Seconds this call may take, the response included, before it raises OpenEmailNetworkError with is_timeout. It overrides the client's timeout for this call, and 0 turns the limit off.

Kthen

KeyResource, one of two dicts. For an API key it is ApiKeySelfResource, with object set to 'api_key', kind, id, mode, scopes, grantedScopes, roleId, workspaceId, addressAllowlist and domainAllowlist. For an OAuth access token it is OauthTokenSelfResource, with object set to 'oauth_token', the same keys with id and roleId set to None, plus clientId and expiresAt. Compare object before reading clientId, and a type checker narrows the union for you.

Shembull

from openemail import openemail key = openemail.me.get() removed_by_role = sorted(set(key['grantedScopes']) - set(key['scopes']))print(key['mode'], key['workspaceId'], removed_by_role) if key['object'] == 'oauth_token':    print(key['clientId'], key['expiresAt'])

Shënime

  • Narrowing a role takes effect on the next request without touching the key itself, so scopes can shrink between two calls with the same secret. Replacing the secret is a separate act, and me.rotate is the call that does it.

  • roleId is None on a key with no ceiling, which is what every key issued before roles existed still has.

  • A failure here raises OpenEmailApiError with status 401 and a code naming the credential problem: missing_api_key, invalid_api_key, revoked_api_key, expired_api_key, or inactive_api_key for a key switched off in the console.

  • An access token that has run out is a 401 expired_access_token, which the app answers by renewing it with its refresh token. invalid_access_token and the grant_* codes mean the app has to be connected again.

E disponueshme edhe në

API
GET /keys/self
TypeScript
me.get()
Ruby
me.get
CLI
openemail me get

me.ping()

Check that a key or access token authenticates

Pa leje
Nënshkrimi
def ping(*, api_key: str | None = None, timeout: float | None = None) -> PingResource

An authentication smoke test. It runs the same key check every other endpoint runs and answers with ok set to True, the key id, its mode, the workspace and the effective scopes. It needs no scope, so a key with none at all still gets a 200.

Use it in a health check or at process start to fail fast on a revoked, expired or mistyped key. The answer carries the same scope detail as me.get, scopes effective and grantedScopes as created with roleId naming the cap between them, but it leaves out both allowlists. Call me.get when you need to know which domains and which addresses the key may send as.

An OAuth access token gets the same answer with kind set to 'oauth', keyId and roleId set to None, clientId naming the connected app and mode always 'live'. A key answers with kind set to 'apiKey'.

Parametrat

api_keystr

Checks this key instead of the credential the client was built with.

timeoutfloat

Seconds this call may take, the response included, before it raises OpenEmailNetworkError with is_timeout. It overrides the client's timeout for this call, and 0 turns the limit off.

Kthen

PingResource, a dict with ok set to True, kind, keyId, mode, scopes, grantedScopes, roleId and workspaceId, plus clientId for an OAuth access token.

Shembull

from openemail import openemail ping = openemail.me.ping() if 'emails:send' not in ping['scopes']:    raise RuntimeError(f'Key {ping["keyId"]} cannot send mail')

Shënime

  • The id is keyId here and id on me.get, and there is no object key in this response, so tell a key from a token by kind.

  • A bad key never comes back with ok set to False. The call raises an OpenEmailApiError with status 401, so is_auth is the check to make.

E disponueshme edhe në

API
GET /ping
TypeScript
me.ping()
Ruby
me.ping
CLI
openemail me ping

me.rotate()

Replace the calling key's own secret

Lejetkeys:write
Nënshkrimi
def rotate(    *,    api_key: str | None = None,    timeout: float | None = None,) -> RotatedKeyResource

Mints a new secret for the key making the call and returns the key as me.get describes it, without kind, plus token, the new key in full. That is the only place the value appears, so store it before anything else.

Everything else about the key survives. The id, the mode, the scopes, the role ceiling, the address allowlist and the domain allowlist all come back unchanged, so token is the only thing your configuration has to change. Because the id is stable, an audit trail joined on it stays joined up across rotations.

There is no overlap window. The old secret stops authenticating the moment this call commits, and neither secret can be shown again. Write token to wherever the key is read from before the next request, and build the next client from it, because a client keeps sending the secret it was created with. A lost response is the bad case: the rotation may have committed to a secret nobody saw, which leaves the key unusable until someone mints it a new secret in the console.

Parametrat

api_keystr

Rotates this key instead of the one the client was built with.

timeoutfloat

Seconds this call may take, the response included, before it raises OpenEmailNetworkError with is_timeout. It overrides the client's timeout for this call, and 0 turns the limit off.

Kthen

RotatedKeyResource, a dict with object set to 'api_key', id, mode, scopes, grantedScopes, roleId, workspaceId, addressAllowlist and domainAllowlist, then token, rotationCount and rotatedAt. token is the new key: oe_live_ or oe_test_, the 24 character key id, an underscore and 43 base64url characters.

Shembull

from pathlib import Path from openemail import openemail rotated = openemail.me.rotate() Path('openemail-api-key').write_text(rotated['token']) print(f'Rotation {rotated["rotationCount"]} committed at {rotated["rotatedAt"]}')

Shënime

  • It needs keys:write, and a key without it gets 403 insufficient_scope. No key holds that scope unless somebody gave it one in the console, so a key that cannot reach this call has to be rotated from there.

  • Only an API key can rotate its own secret. Called with an OAuth access token it raises a 403 api_key_only, because an app renews its token with its refresh token instead.

  • There is no request body and the success status is 200, not 201.

  • Not retried automatically. Repeating a rotation would invalidate the secret the first attempt returned, so a failure has to be judged rather than retried.

  • The 404 and the two 409s are races rather than everyday answers, because a key that is missing, revoked or expired cannot authenticate this call in the first place. They mean the key changed state between authenticating and rotating: 404 if the row went, 409 revoked or 409 expired otherwise. None of the three is rotatable, so the answer is a new key from the console.

  • rotationCount is the count after this call, so the first rotation of a key answers 1, and rotatedAt is when that rotation committed.

E disponueshme edhe në

API
POST /keys/self/rotate
TypeScript
me.rotate()
Ruby
me.rotate
CLI
openemail me rotate