Skip to main content

Verne Software Python SDK

PyPI version Python License: MIT

The official Python library for the Verne Nautilus platform.

Server-side only. API keys carry full service access and must never be used in client-side or browser contexts.

Requirements

Python 3.9 or later.

Installation

pip install vernesoft

Quick Start

from vernesoft import Verne

verne = Verne(
    relay=os.environ["VERNE_RELAY_KEY"],
    gate=os.environ["VERNE_GATE_KEY"],
)

You can also instantiate services independently if you only need one:

from vernesoft import Relay, Gate

relay = Relay(api_key=os.environ["VERNE_RELAY_KEY"])
gate  = Gate(api_key=os.environ["VERNE_GATE_KEY"])

Relay — Webhooks-as-a-Service

Send events to all subscribed endpoints:

msg = verne.relay.messages.send(
    event_type="user.created",
    payload={"id": "usr_123"},
)

Optional parameters:

msg = verne.relay.messages.send(
    event_type="order.placed",
    payload={"order_id": "999"},
    idempotency_key="evt_abc",  # prevent duplicate delivery within 24h
    channels=["team-a"],        # restrict to specific endpoint channels
)

List previously sent events:

page = verne.relay.messages.list(limit=20, event_type="user.created")

print(page.data)        # list[Message]
print(page.has_more)    # bool
print(page.next_cursor) # pass to the next call to paginate

Gate — Auth-as-a-Service

Identity Management

Manage your end-users. The tenant_id is automatically scoped to your API key.

# Create a user
identity = verne.gate.identities.create(
    schema_id="user",
    traits={
        "email": "user@example.com",
        "custom_data": {"role": "editor"},
    },
    credentials={"password": {"config": {"password": "StrongPassword123!"}}},
    state="active",
)

# Get a user
verne.gate.identities.get(identity.id)

# Update a user (JSON Patch — RFC 6902)
verne.gate.identities.patch(identity.id, [
    {"op": "replace", "path": "/traits/custom_data/role", "value": "admin"},
])

# Delete a user
verne.gate.identities.delete(identity.id)

# Activate / deactivate a user (an inactive user cannot log in)
verne.gate.identities.deactivate(identity.id)
verne.gate.identities.activate(identity.id)
# …or set the state explicitly:
verne.gate.identities.set_state(identity.id, "inactive")

# Resend the email verification link
verne.gate.identities.resend_verification(identity.id)

Security Settings

Read or replace the tenant's security settings (passwordless login, TOTP MFA):

security = verne.gate.settings.get_security()
# security.passwordless_enabled, security.mfa_enabled

# Both fields are required — the update is a full replacement, not a merge.
verne.gate.settings.update_security(passwordless_enabled=True, mfa_enabled=False)

Access Tokens

Exchange your long-lived API key for a short-lived access token:

token = verne.gate.tokens.create(
    subject="usr_123",
    scopes=["gate.tokens.read"],  # optional
    ttl_seconds=3600,             # optional, default 3600, max 86400
)

# token.access_token — attach to downstream requests
# token.expires_at   — ISO 8601 expiry

Validate a token:

info = verne.gate.tokens.introspect(token.access_token)

if not info.active:
    # token is expired or invalid
    pass

Authorization

Check whether a subject is allowed to perform an action:

decision = verne.gate.authorize(
    subject="usr_123",
    action="relay.messages.read",
    resource="tenant:ten_001",
)

if not decision.allowed:
    raise PermissionError("Forbidden")

Clockwork — Cron-as-a-Service

Schedule recurring HTTP callbacks with cron expressions, or one-shot jobs at a future time. The tenant_id is automatically scoped to your API key.

Cron Jobs

# List all cron jobs
jobs = verne.clockwork.jobs.list()  # list[CronJob]

# Create a recurring job
job = verne.clockwork.jobs.create(
    name="nightly-report",
    schedule="0 2 * * *",              # standard cron expression
    url="https://example.com/hooks/report",
    method="POST",                     # optional, defaults server-side
    headers={"X-Api-Key": "secret"},   # optional
    body='{"kind":"report"}',          # optional
)

# Partially update a job — only the fields you pass are changed
verne.clockwork.jobs.update(job.id, schedule="0 3 * * *", is_active=False)

# Inspect execution history
executions = verne.clockwork.jobs.executions(job.id)  # list[Execution]

# Delete a job
verne.clockwork.jobs.delete(job.id)

Delayed Jobs

One-shot jobs that fire once at run_at:

# Schedule a delayed job
delayed = verne.clockwork.delayed.create(
    name="welcome-email",
    run_at="2026-07-26T09:00:00Z",     # ISO 8601 timestamp
    url="https://example.com/send",
    body='{"template":"welcome"}',      # optional
)

# List pending / completed delayed jobs
verne.clockwork.delayed.list()  # list[DelayedJob]

# Inspect execution history
verne.clockwork.delayed.executions(delayed.id)  # list[Execution]

# Cancel a pending delayed job
verne.clockwork.delayed.cancel(delayed.id)

Async Support

Every client has an async counterpart — AsyncVerne, AsyncRelay, AsyncGate, AsyncClockwork — with the same interface, where all methods are coroutines:

from vernesoft import AsyncVerne

verne = AsyncVerne(
    relay=os.environ["VERNE_RELAY_KEY"],
    gate=os.environ["VERNE_GATE_KEY"],
)

msg      = await verne.relay.messages.send(event_type="user.created", payload={"id": "usr_123"})
page     = await verne.relay.messages.list(limit=10)
identity = await verne.gate.identities.create(schema_id="user", traits={"email": "a@b.com"})
token    = await verne.gate.tokens.create(subject="usr_123")
decision = await verne.gate.authorize(subject="usr_123", action="relay.messages.read", resource="tenant:ten_001")

Error Handling

All API errors raise VerneAPIError with structured fields:

from vernesoft import VerneAPIError, VerneError

try:
    verne.relay.messages.send(event_type="ping", payload={})
except VerneAPIError as e:
    print(e.code)       # e.g. 'invalid_payload', 'unauthorized'
    print(e.status)     # HTTP status code
    print(e.request_id) # include in support requests
except VerneError as e:
    # network failure or timeout
    print(e)

Configuration

Both Verne and the per-service clients accept an optional timeout in seconds (default 30):

verne = Verne(
    relay=os.environ["VERNE_RELAY_KEY"],
    timeout=10,
)

Individual requests can be cancelled by passing an httpx timeout or by closing the client. Per-request timeouts are supported natively through httpx:

import httpx
from vernesoft import Relay

relay = Relay(api_key=os.environ["VERNE_RELAY_KEY"], timeout=5)

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vernesoft-1.3.0.tar.gz (63.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vernesoft-1.3.0-py3-none-any.whl (23.7 kB view details)

Uploaded Python 3

File details

Details for the file vernesoft-1.3.0.tar.gz.

File metadata

  • Download URL: vernesoft-1.3.0.tar.gz
  • Upload date:
  • Size: 63.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for vernesoft-1.3.0.tar.gz
Algorithm Hash digest
SHA256 a6fd8d7c4e6c7ba5f8838d90a4ac9d5b7d5cef2bef8c9e4493915d6a06625c1a
MD5 c8ba4122f34fb1f26a2c9a4cb842225a
BLAKE2b-256 1e065ad5c245e4ae7693bfa0d336a41980127322ebeeaac400f821054cb45fbb

See more details on using hashes here.

File details

Details for the file vernesoft-1.3.0-py3-none-any.whl.

File metadata

  • Download URL: vernesoft-1.3.0-py3-none-any.whl
  • Upload date:
  • Size: 23.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for vernesoft-1.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6b3c2170ef6aa368b7d82775b4d615ea4bb0b82ab84a6ee8932cd2d58758eea5
MD5 08a99d9245b9044678b480cc976f5a35
BLAKE2b-256 f3e76fadbf3464b16d225594c495900625552e8ba15198a831e6c93e9c6be950

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.3.0 This release

2 files

1.2.0

2 files

1.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page