Python SDK: 0.6.0 — 2026-08-27

Recover a Webhook Delivery Your Receiver Missed

What changed: Three new methods let you inspect and re-send webhook deliveries: webhook_deliveries() lists every attempt for a webhook with what your receiver returned, replay_delivery() re-sends one, and retry_failed_deliveries() re-sends every delivery that exhausted Nimbio’s own retries. Previously a failed delivery was visible but nothing could act on it.

Where to find it: client.community.webhook_deliveries(webhook_id) and its two companions

What you’ll see: Each attempt’s status, attempt count, last status code and last error. A replay appears as a new pending delivery alongside the original, which keeps its own failed record.

What you need to do: Confirm your handler de-duplicates on the X-Nimbio-Delivery header before you replay anything. A replay re-sends the original event id and payload byte for byte, so a receiver that ignores that header will apply the event a second time — a second charge, a second gate open. Also note a replay is signed with your current secret, so a delivery replayed after a secret rotation will be rejected by a receiver still checking the old one.

Who this affects: Customers integrating with the Python SDK


Recurring Hold Opens Are Now Writable

What changed: Business hours, trash day and the standing delivery window can now be created, changed and removed from code. You can also suspend every scheduled hold open on a single gate until a moment you name, and resume it.

Where to find it: client.community.add_hold_open_recurring(), update_hold_open_recurring(), remove_hold_open_recurring() and set_hold_open_disabled_until()

What you’ll see: Schedules round-trip — the id the hold-opens read already returns is the one you edit and post back.

What you need to do: Two rules worth knowing before you write one. Days are letters from MTWHFSU, where H is Thursday, S is Saturday and U is Sunday, and times are in the gate’s own local timezone, never UTC. A window cannot run past midnight, so split 22:0006:00 into two halves using "24:00" rather than "23:59" to leave no gap. Removing a schedule that isn’t on that gate deliberately fails rather than succeeding quietly, so you can never believe you cancelled something that is still holding a gate open.

Who this affects: Customers integrating with the Python SDK


Bulk Member Management and Richer Community Reads

What changed: Seven new methods for working with a roster at size — approve a pending member, rename or disable a key, add members in bulk, and grant, revoke or disable keys across many members in one call. Plus paged and searchable member listing, single-member lookup, sent-message history, and a community description call that reports gate ids and which features are switched on.

Where to find it: client.community.info(), members_page(), member(), approve_member(), bulk_add_members() and the three bulk key methods

What you’ll see: members_page() searches across first name, last name and phone number, ignoring punctuation, and pages through large rosters instead of returning everything at once.

What you need to do: No action needed. Call info() first in a new integration — it is the bootstrap call that tells you your gate ids and which features are on, so you can branch on a flag instead of calling an endpoint and interpreting a 403.

Who this affects: Customers integrating with the Python SDK


Clearer Conflict Errors and Built-In Constants

What changed: HTTP 409 now raises a dedicated ConflictError instead of a generic API error, and the SDK ships the capability and event-type vocabularies as constants.

Where to find it: ConflictError and the constants module

What you’ll see: A 409 is usually something you can act on rather than a failure — Nimbio is already retrying a delivery, a webhook is disabled and you can re-enable it yourself, or an action needs confirming with a repeat call. Catching ConflictError tells these apart from a real error.

What you need to do: No action needed. If you feature-detect off your key’s capabilities, you can now reference the constants instead of typing the strings by hand, where a typo silently reads as “feature off”. They are convenience snapshots, not a closed set — an unfamiliar capability or event type is still accepted, so an older client keeps working when we add one.

Who this affects: Customers integrating with the Python SDK


Read and Change Your Community’s Settings

What changed: Two new methods read and update a community’s feature flags and its member/home terminology. The read also reports which features are switched on, which is the reliable way to find out before you call something.

Where to find it: client.community.settings() and client.community.update_settings()

What you’ll see: The settable fields, a read_only block of Nimbio-managed flags, and the resolved terminology labels your community uses. Several endpoint families are gated on those read-only flags, so this call tells you a feature is off instead of you discovering it through a permission error.

What you need to do: No action needed. If you do write settings, note that a patch is all-or-nothing: one bad value means nothing is applied, so you never end up with a half-changed configuration. A handful of flags are Nimbio-managed provisioning decisions and will be refused with a message telling you which — ask us and we can turn them on.

Who this affects: Customers integrating with the Python SDK


Manage Homes and Move-Out Dates

What changed: Full management of the homes (units) in a community — list, read, add, update and remove — plus recording a member’s move-out date so their access lapses without anyone remembering to revoke it.

Where to find it: client.community.homes(), home(), add_home(), update_home(), remove_home() and set_move_out_date()

What you’ll see: Each home with its address, resident count and hidden state. Listing includes hidden homes by default, which is what a roster sync wants; ask for visible-only to match what the portal shows.

What you need to do: Take care with removal. Deleting a home detaches every resident attached to it — they stay members and keep their keys, but they are no longer attached to any unit, and nothing puts that back automatically. The response tells you how many were detached; read the home first if you want to know before you commit.

Who this affects: Customers integrating with the Python SDK


Member-Open Alerts and Quiet Hours

What changed: Read and control your member-open notifications, and add or remove the quiet-hours windows that suppress them.

Where to find it: client.community.my_notification_settings() and its three companions

What you’ll see: Whether alerts are on, whether the community allows them at all, and your current quiet-hours windows. Every one of the four calls returns the full settings object, so nothing needs a follow-up read.

What you need to do: Two things are easy to get wrong. These settings belong to the manager whose key you are using, not to the community — a community with several managers has several independent settings, so switching alerts off with one key does not quiet anyone else. And a quiet-hours window here may wrap past midnight: 22:00 to 06:00 is one window, unlike gate schedules and recurring hold opens, which need two. Each window is evaluated on the clock of the gate that was opened, not yours.

Who this affects: Customers integrating with the Python SDK


Your Integration Now Uses Less of Its Monthly Quota, Automatically

What changed: The client now makes conditional requests. It remembers a fingerprint of each response and, on the next identical read, asks the server “has this changed?” — and when the answer is no, the server sends nothing back and does not charge that call against your monthly quota.

Where to find it: Nothing to find — it is on by default for every read that supports it.

What you’ll see: Lower monthly usage on client.me(), particularly for anything that polls: gate status, member lists, hold opens. client.cache_stats() shows how often it is working.

What you need to do: No action needed. Two things worth knowing: this reduces your monthly quota use but not your per-minute rate limit, so it is not a licence to poll faster; and it can never hand you stale data, because it always asks the server first and only reuses a stored copy when the server confirms nothing changed. If you would rather turn it off, pass cache=False when constructing the client.

Who this affects: Customers integrating with the Python SDK


Issue and Revoke Guest Access From Your Own System

What changed: Full guest access over the API — guest links, directory access codes, GuestView Entry settings and schedules, and short codes. A booking or property-management system can hand a visitor a working gate link the moment a reservation is confirmed, and kill it at checkout.

Where to find it: client.community.guest_links(), create_guest_link(), access_codes(), guest_view_entry(), short_codes() and their companions

What you’ll see: Links come back with a ready-to-send URL and a live state — active, upcoming, expired, spent or revoked. Event links allow unlimited opens inside a time window; limited-use links allow a set number of opens.

What you need to do: Treat these responses as secrets. The link URL is returned by the listing call as well as by create, so a leaked listing is a leaked set of working gate links — anyone holding one opens the gate with no account and no login. Don’t log them. Also note that replacing the gates GuestView Entry covers replaces the whole set: read the current settings and send back a modified copy, or you will silently remove other gates and their schedules.

Who this affects: Customers integrating with the Python SDK


Diagnose a Misreporting Gate Yourself

What changed: The physical layer underneath gate status is now readable and configurable — sense lines and their raw transition records, NFC tag lifecycle and scan history, the community map with per-gate geofences, plus configuration change logs and key-usage reporting. This completes the client: every documented API operation is now wrapped.

Where to find it: client.community.sense_lines(), sense_line_records(), nfc_tags(), map() and update_geofence()

What you’ll see: For each sense line, a reporting flag that tells you whether its readings are actually allowed to drive gate status. A gate stuck on one status with reporting false is a configuration problem, not a stuck gate — and because raw records are written even when a sense line is switched off, a healthy record stream next to a stale gate status proves the wiring is fine and the configuration is not.

What you need to do: No action needed. If you do reconfigure a sense line, know that switching it off freezes that gate’s reported status everywhere — in the apps, in this API, and in the event stream. Turning a miswired input off is a legitimate repair; doing it by accident is not.

Who this affects: Customers integrating with the Python SDK


Manage Lost and Stolen Fobs

What changed: NFC tags — the physical fobs and cards that open a gate on tap — can be listed, searched, assigned to a gate, detached, and disabled, with a scan log that makes a lost one traceable.

Where to find it: client.community.nfc_tags(), nfc_tag(), update_nfc_tag() and nfc_scan_log()

What you’ll see: Disabling a tag takes effect for real gate taps — the next tap is refused. The scan log attributes taps to a member where the tap resolved to one, so a security review can tell you who used which fob, where and when.

What you need to do: Disabling is an explicit setting rather than a toggle, so revoking a stolen fob never depends on state you read a moment earlier. If a change would leave a scan-only gate with no working tag, the call asks you to confirm rather than refusing outright — repeat it with confirmation. That is deliberate: revoking a stolen fob has to stay possible.

Who this affects: Customers integrating with the Python SDK

Control Access to your property with the Nimbio app

Discover how Nimbio's cellular-based system can enhance security, increase convenience, and simplify access control for your property.
Call Now