Python SDK for the Vorlek email-marketing aggregation API
Project description
Vorlek Python SDK
Python client for the Vorlek API. It exposes the Phase 2 tool surface with
automatic idempotency keys, normalized {data, meta} results, and typed
exceptions for API and network failures.
pip install vorlek
Requires Python 3.10 or newer.
Quickstart (sync)
import os
from vorlek import VorlekClient
with VorlekClient(api_key=os.environ["VORLEK_API_KEY"]) as client:
result = client.contact.upsert(
provider="sendgrid",
email="jamie@example.com",
first_name="Jamie",
properties={"plan": "free"},
)
print(result.data["contact_id"])
print(result.meta.request_id)
catalog = client.catalog.get()
print([tool["name"] for tool in catalog.data["tools"]])
operation = client.operations.get(result.meta.request_id)
print(operation.data["status"])
minimal = client.contact.upsert(
provider="sendgrid",
email="minimal@example.com",
detail="minimal",
)
print(minimal.meta.detail)
Quickstart (async)
import asyncio
import os
from vorlek import AsyncVorlekClient
async def main() -> None:
async with AsyncVorlekClient(api_key=os.environ["VORLEK_API_KEY"]) as client:
result = await client.connection.status(provider="sendgrid")
print(result.data["status"])
print(result.meta.request_id)
asyncio.run(main())
Methods
All tool calls are keyword-only and return VorlekResult[T], where
result.data is the normalized tool payload and result.meta includes the
request id, quota state, rate-limit state, and idempotency replay state when
present.
result.data is parsed JSON: at runtime it is dict[str, object], even
though the per-tool aliases (UpsertContactResult, SendTransactionalResult,
etc.) point at the generated dataclasses for type-checker convenience. Use
subscript syntax — result.data["contact_id"], not result.data.contact_id.
| Namespace | Method | Endpoint |
|---|---|---|
client.contact |
upsert(...) |
POST /v1/tools/upsert_contact |
client.connection |
status(...) |
POST /v1/tools/get_connection_status |
client.send |
transactional(...) |
POST /v1/tools/send_transactional |
client.campaign |
stats(...) |
POST /v1/tools/get_campaign_stats |
client.campaign |
list(...) |
POST /v1/tools/list_campaigns |
client.template |
list(...) |
POST /v1/tools/list_templates |
client.catalog |
get() |
GET /v1/catalog |
client.operations |
get(request_id) |
GET /v1/operations/{request_id} |
Supported providers are sendgrid, mailchimp, and klaviyo. Argument
types are generated from the live OpenAPI schema and are also documented at
https://vorlek.dev/openapi.json.
Tool methods accept detail="minimal", detail="standard", or
detail="full". minimal trims envelope metadata, standard is the default,
and full adds operation lookup metadata.
client.template.list(query="welcome") filters the returned template page
across id, name, and subject. When the page has no match, inspect
result.data["search"]["no_match"] for the suggested next action.
client.contact.get(provider="sendgrid", email="test@example.com") reads one
contact by email for same-surface read-after-write verification after an
upsert.
Error handling
Vorlek raises subclasses of VorlekError. Caller mistakes are grouped under
VorlekClientError, while more specific classes let applications handle common
cases directly.
from vorlek import (
VorlekClient,
VorlekClientError,
VorlekError,
VorlekRateLimitedError,
is_retryable_error,
)
client = VorlekClient(api_key="vk_live_...")
try:
result = client.contact.upsert(provider="sendgrid", email="jamie@example.com")
except VorlekRateLimitedError as err:
print(f"rate limited, retry after {err.retry_after} seconds")
except VorlekClientError as err:
print(f"fix the request before retrying: {err.code} {err.message}")
except VorlekError as err:
if is_retryable_error(err):
print(f"retry with backoff: {err.code}")
else:
print(f"not retry-safe: {err.code}")
else:
print(result.data)
finally:
client.close()
Every error exposes code, category, retry_safe, http_status,
request_id, provider, retry_after, and detail.
Idempotency
Every tool call sends an Idempotency-Key header. By default the SDK generates
a fresh ULID per request.
Pass idempotency_key to retry one logical operation with the same key:
result = client.contact.upsert(
provider="mailchimp",
email="jamie@example.com",
idempotency_key="01HV0011V0110011V011001100",
)
print(result.meta.idempotency.replay if result.meta.idempotency else False)
Calling the same key twice with the same request body is safe. Reusing the same
key with a different body raises VorlekIdempotencyConflictError.
from_ on transactional sends
Python reserves from as a keyword, so the SDK accepts from_ and sends it to
the API as from.
client.send.transactional(
provider="sendgrid",
to="jamie@example.com",
from_="updates@example.com",
subject="Welcome",
text="Thanks for trying Vorlek.",
)
Test mode
vk_test_* keys pass through the SDK today. Full test-mode behavior, including
provider-free deterministic tool responses, is planned for Phase 3.6 and will
be documented at https://vorlek.dev/docs/test-mode when it ships.
Examples
The examples/ directory contains small scripts that run from a virtual
environment:
export VORLEK_API_KEY=vk_live_...
python examples/upsert.py
python examples/send_transactional.py
python examples/cross_provider_round_trip.py
Each script exits successfully with a skip message when required environment variables are missing.
Cross-SDK parity
The TypeScript SDK is published as @vorlek/sdk. Both SDKs surface the same
{data, meta} success contract and the same six tool namespaces. Python v1
ships the full 18-class error hierarchy; the TypeScript retrofit is tracked at
https://github.com/vorlek/vorlek-sdk-ts/issues/2.
Local development
python -m venv .venv
. .venv/bin/activate
pip install -e ".[dev]"
ruff check .
ruff format --check .
mypy src/vorlek
pytest -q
python scripts/generate_types.py && git diff --exit-code src/vorlek/_generated/
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 vorlek-1.2.3.tar.gz.
File metadata
- Download URL: vorlek-1.2.3.tar.gz
- Upload date:
- Size: 54.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a47c917cccc253743ecdb6dea97655a6ce44d2945b980f801a1a5ef4e3a69a51
|
|
| MD5 |
eda726576faed6531688ed9c5de6123f
|
|
| BLAKE2b-256 |
1c14b724666c5d6219bad70bff4559cfa7989849b230846931a743c8ed66ecbe
|
File details
Details for the file vorlek-1.2.3-py3-none-any.whl.
File metadata
- Download URL: vorlek-1.2.3-py3-none-any.whl
- Upload date:
- Size: 126.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ce6bab4998a4891169a67a381534615dd20212d97a92c07e419018138cfd130
|
|
| MD5 |
6cd90d3f70ae6bd7c86a19daf1a36bf0
|
|
| BLAKE2b-256 |
1fc01ac70d87b410d1b653fce1673899df5be4e05bc2f8f294d36780dd9e65c6
|