Skip to content

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 YAMA_API_KEY; passing None doesn't fall back to it.

NOT_GIVEN
base_url str | None

Where to send requests; else YAMA_API_BASE_URL, else DEFAULT_BASE_URL.

None
timeout float | Timeout

Seconds allowed for each phase of an attempt (connect, write, read, pool), or an httpx.Timeout to set them one by one.

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 httpx.Client to send through. The client applies its own URL, timeout and headers to each request, and leaves closing it to you. An httpx.AsyncClient isn't supported.

None

Raises:

Type Description
YamaError

No API key was given.

TypeError

api_key isn't a string, timeout isn't a number of seconds or an httpx.Timeout, max_retries isn't an int, or http_client isn't an httpx.Client.

ValueError

The API key isn't printable ASCII without spaces, once stripped, base_url doesn't start with https:// or http://, or max_retries is negative.

api_key instance-attribute

api_key: ApiKeyResource

The API key the client uses: what it may do.

buildings instance-attribute

buildings: Buildings

Your buildings.

units instance-attribute

units: Units

Your units.

contacts instance-attribute

contacts: Contacts

The contacts on your units.

codes instance-attribute

codes: Codes

The access codes on your units.

calls instance-attribute

calls: Calls

The call log.

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

Your buildings (read-only).

list

list() -> Iterator[Building]

Every building, fetched as you iterate.

get

get(uuid: UUID | str) -> Building

One building. Raises NotFoundError if it isn't within the API key's reach.

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 APITimeoutError, the last attempt timed out, so the create may have happened; send it again later with the same idempotency key.

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

idempotency_key isn't 1 to 255 printable ASCII characters, without spaces.

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

start or end is a date, or anything else but a datetime.

ValueError

start or end has no time zone, or end is before start.

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.

expires_at instance-attribute

expires_at: AwareDatetime | None

None for a key that never expires.

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.

status_code instance-attribute

status_code = status_code

The HTTP status code.

detail instance-attribute

detail = detail

The body's detail, or else its field errors joined, or else the HTTP reason.

body instance-attribute

body = body

The parsed JSON body, or its text when it isn't JSON.

api_version instance-attribute

api_version = api_version

The response's API-Version header.

method instance-attribute

method = method

The request's HTTP method.

path instance-attribute

path = path

The request's URL path, without its query string.

request_id instance-attribute

request_id = request_id

The response's Request-Id header, which Yama support asks for to find the request; None when it has none.

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,
)

Bases: APIStatusError

401: the API key is malformed, unknown, deleted or expired.

PermissionDeniedError

PermissionDeniedError(
    status_code: int,
    detail: str,
    body: object,
    api_version: str | None,
    method: str,
    path: str,
    request_id: str | None = None,
)

Bases: APIStatusError

403: the API key lacks the permission this operation needs.

NotFoundError

NotFoundError(
    status_code: int,
    detail: str,
    body: object,
    api_version: str | None,
    method: str,
    path: str,
    request_id: str | None = None,
)

Bases: APIStatusError

404: no such object within the API key's reach.

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,
)

Bases: APIStatusError

5xx: the API failed.

Testing

fake_transport

fake_transport() -> httpx.MockTransport

An httpx.MockTransport serving a new in-memory Yama API with its own made-up data.