Reference¶
Everything here is importable from yama, except the resources below, and fake_transport, which is in yama.testing. Models and enums are also in yama.models.
Client¶
Yama ¶
Yama(
api_key: str | None = NOT_GIVEN,
*,
base_url: str | None = None,
timeout: float | Timeout = 30.0,
max_retries: int = 2,
http_client: Client | None = None,
)
A client for the Yama API.
Use it as a context manager, or call close() when done. One client can be shared
between threads.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
api_key
|
str | None
|
The API key. Defaults to |
NOT_GIVEN
|
base_url
|
str | None
|
Where to send requests; else |
None
|
timeout
|
float | Timeout
|
Seconds allowed for each phase of an attempt (connect, write, read, pool),
or an |
30.0
|
max_retries
|
int
|
How many times to retry a request after a 429, a 5xx or a network error. |
2
|
http_client
|
Client | None
|
Your own |
None
|
Raises:
| Type | Description |
|---|---|
YamaError
|
No API key was given. |
TypeError
|
|
ValueError
|
The API key isn't printable ASCII without spaces, once stripped,
|
with_options ¶
with_options(
*,
timeout: float | Timeout = NOT_GIVEN,
max_retries: int = NOT_GIVEN,
) -> Yama
A copy of the client with a different timeout or max_retries, sharing its
connections, key and base URL, such as a fail-fast client for a web view.
Closing the copy leaves the connections open; closing this client closes them for both.
close ¶
close() -> None
Close the client's connections, unless they belong to the http_client you passed.
Using the client afterwards raises ValueError.
DEFAULT_BASE_URL
module-attribute
¶
DEFAULT_BASE_URL = 'https://app.yamasystems.com'
Where the client sends requests unless base_url or YAMA_API_BASE_URL says otherwise.
Resources¶
The client's attributes, such as client.codes; you don't create these yourself. Each method is one API operation.
client.api_key¶
The API key the client uses.
get ¶
get() -> ApiKeyDetails
What the API key may do: its permissions, scopes, unit access and expiry. Any valid API key can read this, so it's a good first call.
client.buildings¶
client.units¶
Your units (read-only).
list ¶
list(
*,
building: UUID | str | None = None,
door_digit: DoorDigit | str | None = None,
search: str | None = None,
) -> Iterator[Unit]
Every unit, or only those in building, with door_digit, or whose name contains
search (case-insensitive).
get ¶
get(uuid: UUID | str) -> Unit
One unit. Raises NotFoundError if it isn't within the API key's reach.
client.contacts¶
The contacts a visitor can be forwarded to (read-only).
list ¶
list(
*,
unit: UUID | str | None = None,
number: str | None = None,
menu_digit: str | None = None,
) -> Iterator[Contact]
Every contact, or only those on unit, with phone number (E.164), or reached
with menu_digit.
get ¶
get(uuid: UUID | str) -> Contact
One contact. Raises NotFoundError if it isn't within the API key's reach.
client.codes¶
The access codes on your units.
list ¶
list(
*,
unit: UUID | str | None = None,
code: str | None = None,
name: str | None = None,
search: str | None = None,
) -> Iterator[AccessCode]
Every access code, or only those on unit, with exactly the digits code, with
exactly the name name, or whose name contains search (case-insensitive).
get ¶
get(uuid: UUID | str) -> AccessCode
One access code. Raises NotFoundError if it isn't within the API key's reach.
create ¶
create(
data: AccessCodeCreate,
*,
idempotency_key: str | None = None,
) -> AccessCode
Create an access code.
Sent with an idempotency key, so retries never create the code twice. Pass
idempotency_key (1 to 255 printable ASCII characters, without spaces) to repeat a
create yourself; see the errors guide. When the create fails, the error's
idempotency_key is the idempotency key that was sent.
Raises:
| Type | Description |
|---|---|
BadRequestError
|
A field is invalid, such as a code the unit already has. |
ConflictError
|
A create with this idempotency key was still running after the retries; send it again later with the same idempotency key. |
APIConnectionError
|
The network failed after the retries, or, as |
GoneError
|
The create with this idempotency key did happen, but the code has since been deleted or is out of the API key's reach. Don't repeat it with this idempotency key. |
UnprocessableEntityError
|
This idempotency key was already used with different data. |
ValueError
|
|
replace ¶
replace(
uuid: UUID | str, data: AccessCodeCreate
) -> AccessCode
Replace an access code. Leaving name or expires_at unset keeps its current
value, and None clears it.
update ¶
update(
uuid: UUID | str, data: AccessCodeUpdate
) -> AccessCode
Change the fields of an access code set in data. Set name or expires_at to
None to clear it, such as AccessCodeUpdate(expires_at=None) for a code that never
expires.
delete ¶
delete(uuid: UUID | str) -> None
Delete an access code; it stops working at once.
A 404 on a retry counts as done, since an earlier attempt may have deleted it.
client.calls¶
The call log (read-only).
list ¶
list(
*,
start: datetime | None = None,
end: datetime | None = None,
unit: UUID | str | None = None,
building: UUID | str | None = None,
result: CallResult | str | None = None,
) -> Iterator[CallLogEntry]
Every call that started at or after start and before end, newest first, or only
those to unit, through the intercom of building, or with result.
start and end are timezone-aware datetimes, so one local day is from its midnight
to the next, in any time zone. Leaving one out leaves that side of the range open, so
with neither you get all history. With a start, polling for recent calls is cheap.
Each call is yielded once, even when new calls arrive while you iterate.
Raises:
| Type | Description |
|---|---|
TypeError
|
|
ValueError
|
|
get ¶
get(uuid: UUID | str) -> CallLogEntry
One call, whatever its date. Raises NotFoundError if it isn't within the API key's
reach.
Models¶
The models the client takes and returns, and the enums their fields use.
Response models mirror the API's schema field for field. They're frozen, keep fields the
client doesn't know (read them as attributes, or from model_extra), and give an enum value
the client doesn't know as a plain string, so compare with ==. Enum members format as their
value, so str() and f-strings give the same text either way. Request models reject unknown
fields, datetimes without a time zone, and values the schema doesn't allow, such as a code that
isn't 3 to 15 digits. Rules that depend on the API's data or clock are left to the API.
AccessLevel ¶
What an API key may do with a resource.
UnitAccessType ¶
Which units an API key reaches: all of them, those in some buildings, or some units.
DoorDigit ¶
The digit Yama sends to a building's intercom to open the door for a unit.
CallResult ¶
How a call ended.
CallStepKind ¶
What happened at one step of a call.
CodeAttemptResult ¶
How a code entered at the intercom was judged.
DialStatus ¶
How a forwarded call ended.
ApiKeyPermissions ¶
An API key's access level for each resource.
ApiKeyUnitAccess ¶
The units an API key reaches: buildings and units list the selected ones.
ApiKeyDetails ¶
The API key that sent the request: what it may do, never the key itself.
Building ¶
A building, with the number its intercom calls from and how many of your units it has.
Unit ¶
A unit in a building.
Contact ¶
Someone a visitor can be forwarded to from a unit's intercom menu.
AccessCode ¶
An access code on a unit.
expires_at
class-attribute
instance-attribute
¶
expires_at: AwareDatetime | None = None
When the code stops working; None for a code that never expires.
CallLogStep ¶
One step of a call. Facts that don't apply to the step are None.
CallLogEntry ¶
A call to a unit through a building's intercom, with its steps.
AccessCodeCreate ¶
A new access code, or the whole of one being replaced.
code is 3 to 15 digits, and name, which is optional, is at most 255 characters. Leave
expires_at out for a code that never expires. When replacing, leaving name or
expires_at out keeps its current value, and None clears it.
AccessCodeUpdate ¶
Changes to an access code: only the fields you set are sent, with the same rules as in
AccessCodeCreate. Setting name or expires_at to None clears it; code and unit
can't be cleared.
Errors¶
The official Python client for the Yama API.
YamaError ¶
Bases: Exception
Base class for every error the client raises. Raised itself for misconfiguration, or a response the client can't read.
idempotency_key
class-attribute
instance-attribute
¶
idempotency_key: str | None = None
The idempotency key a failed codes.create sent, so you can send it again with it;
None for any other call.
APIConnectionError ¶
Bases: YamaError
The request failed at the network level, after retries. It may never have been sent.
APITimeoutError ¶
Bases: APIConnectionError
The last attempt timed out, after retries. The API may still have processed it.
APIStatusError ¶
APIStatusError(
status_code: int,
detail: str,
body: object,
api_version: str | None,
method: str,
path: str,
request_id: str | None = None,
)
Bases: YamaError
The base class for HTTP errors; raised itself for a status without its own class.
Quote its request_id to Yama support when asking about a failed call.
BadRequestError ¶
BadRequestError(
status_code: int,
detail: str,
body: object,
api_version: str | None,
method: str,
path: str,
request_id: str | None = None,
)
Bases: APIStatusError
400: a field or query parameter is invalid, blank or unknown.
errors
property
¶
errors: dict[str, list[str]]
Each invalid field or query parameter (or a key such as non_field_errors),
mapped to its messages.
AuthenticationError ¶
AuthenticationError(
status_code: int,
detail: str,
body: object,
api_version: str | None,
method: str,
path: str,
request_id: str | None = None,
)
PermissionDeniedError ¶
PermissionDeniedError(
status_code: int,
detail: str,
body: object,
api_version: str | None,
method: str,
path: str,
request_id: str | None = None,
)
NotFoundError ¶
NotFoundError(
status_code: int,
detail: str,
body: object,
api_version: str | None,
method: str,
path: str,
request_id: str | None = None,
)
ConflictError ¶
ConflictError(
status_code: int,
detail: str,
body: object,
api_version: str | None,
method: str,
path: str,
request_id: str | None = None,
)
Bases: APIStatusError
409: a request with the same idempotency key is still being processed, after retries.
GoneError ¶
GoneError(
status_code: int,
detail: str,
body: object,
api_version: str | None,
method: str,
path: str,
request_id: str | None = None,
)
Bases: APIStatusError
410: a create repeated with its idempotency key did happen, but the code it created has since been deleted or is out of the API key's reach. Don't create it again with that idempotency key.
UnprocessableEntityError ¶
UnprocessableEntityError(
status_code: int,
detail: str,
body: object,
api_version: str | None,
method: str,
path: str,
request_id: str | None = None,
)
Bases: APIStatusError
422: the idempotency key was already used with a different request. Each create needs its own idempotency key.
RateLimitError ¶
RateLimitError(
status_code: int,
detail: str,
body: object,
api_version: str | None,
method: str,
path: str,
request_id: str | None = None,
retry_after: int | None = None,
)
Bases: APIStatusError
429: too many requests, after retries, or at once when the wait is over 60 seconds.
retry_after
instance-attribute
¶
retry_after = retry_after
Seconds the API asked the client to wait, from Retry-After; None when it didn't
say.
ServerError ¶
ServerError(
status_code: int,
detail: str,
body: object,
api_version: str | None,
method: str,
path: str,
request_id: str | None = None,
)
Testing¶
fake_transport ¶
fake_transport() -> httpx.MockTransport
An httpx.MockTransport serving a new in-memory Yama API with its own made-up data.