Omnidapter API client SDK
Project description
omnidapter-sdk
Python client for the Omnidapter API.
Omnidapter lets you connect to your users' calendars (and other services) through a single unified API. You create a link token, send the user through the Connect UI to authorise their account, and then read their data using the connection that comes back.
Installation
pip install omnidapter-sdk
Requires Python 3.10+.
Getting started
The SDK is async-native — every operation method returns a coroutine that must be awaited. OmnidapterClient is an async context manager; use async with to guarantee the underlying HTTP session is closed:
import asyncio
from omnidapter_sdk import OmnidapterClient
async def main() -> None:
async with OmnidapterClient(
base_url="https://api.example.com",
api_key="omni_live_...",
) as client:
providers = await client.providers.list_providers()
for provider in providers:
print(provider.key, provider.display_name)
asyncio.run(main())
For long-lived clients (e.g. one per FastAPI application), construct directly and call await client.close() at shutdown.
Every operation returns its payload directly — a list for list operations, the resource for single-resource operations. There is no .data wrapper. The per-request correlation id is surfaced on errors as exc.request_id (see Error handling).
Breaking change — unwrapped responses. Methods now return the payload directly instead of an
ApiResponseenvelope: replaceresult.datawithresult(e.g.providers.data→providers,conn.data.status→conn.status). List endpoints return the bare list; the pagingmetais now reached via.rawon the domain accessor (e.g.await client.crm.raw.list_contacts(...)→ the full{data, meta}page) — or just use theiter_*helpers. The previous correlation id onmeta.request_idis now on the raised exception's.request_id.Breaking change — async-native client (0.5.0). Prior versions (≤ 0.4.x) returned plain values from synchronous methods. The client flips every method to
async def; existing call sites must addawaitand wrap construction inasync with(or callawait client.close()explicitly).
Providers
Providers are the services Omnidapter can connect to (e.g. Google, Microsoft). You typically list them once to populate a picker in your UI.
providers = await client.providers.list_providers()
for provider in providers:
print(provider.key, provider.display_name)
# Fetch a single provider by its key
google = await client.providers.get_provider(provider_key="google")
print(google.display_name)
Connections
A connection represents an authorised link between one of your end users and a provider. Once a user completes the Connect flow, their connection appears here.
# List all connections, optionally filtering by status or provider
connections = await client.connections.list_connections(status="active", provider="google")
for conn in connections:
print(conn.id, conn.provider_key, conn.status)
# Fetch a single connection
conn = await client.connections.get_connection(connection_id="conn_...")
print(conn.status)
# Revoke a connection — this also invalidates any stored credentials
await client.connections.delete_connection(connection_id="conn_...")
Link tokens
A link token is a short-lived, single-use token that grants an end user access to the Connect UI. Generate one server-side, pass it to your frontend, and redirect the user to connect_url. Omnidapter will handle the OAuth flow and create a connection on success.
from omnidapter_sdk.models import CreateLinkTokenRequest
result = await client.link_tokens.create_link_token(
create_link_token_request=CreateLinkTokenRequest(
end_user_id="user_123", # your internal user ID
allowed_providers=["google", "microsoft"], # restrict which providers are shown
)
)
token = result # the payload is returned directly
print(token.token) # lt_... — pass this to your frontend
print(token.connect_url) # redirect the user here to start the Connect flow
print(token.expires_at) # datetime — tokens are short-lived, generate them on demand
Calendar
Once a user has a connection, you can read their calendar data. All calendar operations require a connection_id.
from datetime import datetime, timezone
# List the calendars available on a connection
calendars = await client.calendar.list_calendars(connection_id="conn_...")
for cal in calendars:
print(cal.id, cal.name)
# List events within a time range across a specific calendar
events = await client.calendar.list_events(
connection_id="conn_...",
calendar_id="cal_...",
start=datetime(2026, 4, 1, tzinfo=timezone.utc),
end=datetime(2026, 4, 30, tzinfo=timezone.utc),
)
for event in events:
print(event.id, event.title, event.start)
Pagination
A plain list call returns one page of items as a bare list. To see the paging
state, use .raw on the domain accessor — it returns the full {data, meta}
page, where has_more is the signal to keep going (a full page does not
mean the end of the data):
# Just the items for one page:
contacts = await client.crm.list_contacts(connection_id="conn_...", limit=50)
for contact in contacts:
print(contact.id)
# The page envelope, when you need the paging cursor / has_more:
page = await client.crm.raw.list_contacts(connection_id="conn_...", limit=50)
print(page.meta.pagination.has_more) # True → there's another page
print(page.meta.pagination.cursor) # pass as `cursor=` to fetch the next page
Prefer the hand-written iter_* helpers, which walk every page for you and
yield each item:
conn = client.connection("conn_...")
async for contact in conn.iter_contacts():
print(contact.id)
async for booking in conn.iter_bookings():
...
async for event in conn.iter_events("cal_...", start=..., end=...):
...
# Connections page from the top-level client:
async for connection in client.iter_connections():
print(connection.id)
Helpers: iter_contacts, iter_companies, iter_deals, iter_activities,
iter_bookings, iter_events, iter_connections. Each accepts page_size and
forwards list filters as keyword arguments. See
docs/api/pagination.md for the full reference.
Error handling
The SDK raises a typed ApiException subclass for any non-2xx response
(NotFoundException for 404, UnauthorizedException for 401, and so on). Each
carries the HTTP status, the raw error body, and the server's correlation id for
that request — quote request_id when reporting an issue.
from omnidapter_sdk.exceptions import ApiException, NotFoundException
try:
conn = await client.connections.get_connection(connection_id="conn_unknown")
except NotFoundException as e:
print(e.status) # 404
print(e.request_id) # req_... — the server's correlation id for this call
except ApiException as e:
print(e.status) # any other non-2xx
print(e.body) # JSON error body from the server
print(e.request_id) # correlation id (None if the server sent none)
Notes
- The SDK is generated from the server's OpenAPI spec via
scripts/generate_sdks.sh. Run that script after pulling changes to regenerate the client code. - The transport is
aiohttp(via openapi-generator'slibrary=asynciotemplate). Anaiohttp.ClientSessionis opened lazily on the first request and closed when theOmnidapterClientis closed (viaasync withorawait client.close()). Skipping the close emits aResourceWarningfrom aiohttp at process exit.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file omnidapter_sdk-0.6.0.tar.gz.
File metadata
- Download URL: omnidapter_sdk-0.6.0.tar.gz
- Upload date:
- Size: 82.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
071ab78437edb60bb533a13bf4160edbb0c8e61ef13eeba7380b762fa654a95a
|
|
| MD5 |
d5ac09921f4f4ce690b45412656ccb94
|
|
| BLAKE2b-256 |
0fc63573066bf8c41046a41bb88d7d098042e7450851fd346c712714687aebe3
|
File details
Details for the file omnidapter_sdk-0.6.0-py3-none-any.whl.
File metadata
- Download URL: omnidapter_sdk-0.6.0-py3-none-any.whl
- Upload date:
- Size: 219.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
324be898ef896a879b636c48fe762f557cbada7b67bdeb2d5a29d2b62feb0b4e
|
|
| MD5 |
c93662e8895d633dbb10d904fceb9c73
|
|
| BLAKE2b-256 |
519d8b24de8107c034349dd8d1813d9e7004c9abd799d962cbf3cd0f527e8056
|