Skip to main content

Driftstack Python SDK — stealth iPhone Safari automation. Import as `driftstack`.

Project description

Driftstack Python SDK

Stealth iPhone Safari automation, called from Python. Sync (Driftstack) and async (AsyncDriftstack) clients in one package, sharing the same typed resources, error hierarchy, and retry policy.

Status: alpha. The SDK is built, tested, and wheel-buildable, but not yet published to PyPI — gated on entity setup. Until then, install from a local checkout or a tagged commit.

Install

pip install driftstack-sdk

The dist name on PyPI is driftstack-sdk; the import name is driftstack.

Requires Python 3.10+.

Quickstart (sync)

from driftstack import Driftstack

with Driftstack(api_key="ds_live_…") as client:
    session = client.sessions.create({"label": "ci-run"})
    client.sessions.navigate(str(session.id), {"url": "https://example.com/"})
    state = client.sessions.get_state(str(session.id))
    print(state.url, state.title)
    client.sessions.destroy(str(session.id))

Quickstart (async)

import asyncio
from driftstack import AsyncDriftstack

async def main():
    async with AsyncDriftstack(api_key="ds_live_…") as client:
        s = await client.sessions.create()
        await client.sessions.navigate(str(s.id), {"url": "https://example.com/"})
        await client.sessions.destroy(str(s.id))

asyncio.run(main())

Resources

Every public API endpoint is a typed method on a resource accessor:

Accessor Methods
client.sessions create, list, get, navigate, interact, wait, get_state, capture, destroy
client.api_keys create, list, revoke
client.usage current_period
client.webhooks create, list, get, delete, list_deliveries

Inputs accept either a Pydantic model OR a plain dict (both serialize identically on the wire). Outputs are typed Pydantic models — IDEs autocomplete every field.

# Either of these works:
from driftstack._generated.models import CreateSessionRequest
client.sessions.create(CreateSessionRequest(label="ci"))
client.sessions.create({"label": "ci"})

Error handling

Every server application/problem+json response is mapped to a typed exception. The base class is DriftstackError; subclasses cover the documented problem types.

from driftstack import (
    AuthError,
    ConcurrencyLimitError,
    DriftstackError,
    QuotaExceededError,
    RateLimitError,
    ValidationError,
)

try:
    session = client.sessions.create()
except AuthError:
    ...                                    # invalid / expired / revoked key
except ConcurrencyLimitError as e:
    ...                                    # e.current_sessions / e.limit
except QuotaExceededError as e:
    ...                                    # e.current / e.limit / e.record_type
except RateLimitError as e:
    time.sleep(e.retry_after_seconds or 1)
except ValidationError as e:
    ...                                    # e.message has the server's detail
except DriftstackError as e:
    ...                                    # catch-all for anything else

The full hierarchy lives in driftstack/errors.py; the URI → exception mapping is in PROBLEM_TYPE_TO_ERROR.

Retry

Default policy: 3 retries with exponential backoff and full jitter. Honours Retry-After from rate-limit responses. Customize via RetryConfig:

from driftstack import Driftstack
from driftstack.retry import RetryConfig

client = Driftstack(
    api_key="ds_live_…",
    retry=RetryConfig(max_retries=5, initial_delay_ms=500, max_delay_ms=10_000),
)

# Disable entirely for predictable testing:
client = Driftstack(api_key="…", retry=RetryConfig(enabled=False))

Retryable errors by default: TransportError (network / timeout / parse) + RateLimitError. Other typed errors (auth, validation, quota, concurrency) propagate immediately.

Webhook signature verification

Stripe-style HMAC-SHA256 over <unix_seconds>.<raw_body>. Constant-time comparison via hmac.compare_digest. 5-minute default tolerance.

from driftstack import verify_webhook_signature

@app.post("/driftstack-webhook")
def receive():
    raw = request.get_data()                   # framework-specific raw body
    ok = verify_webhook_signature(
        body=raw,
        header=request.headers.get("x-driftstack-signature"),
        secret=os.environ["DRIFTSTACK_WEBHOOK_SECRET"],
    )
    if not ok:
        return ("", 401)
    # ... process event ...
    return ("", 204)

A complete stdlib-only receiver lives in examples/webhook_receiver.py.

Examples

Configuration

client = Driftstack(
    api_key="ds_live_…",          # required
    base_url="https://api.driftstack.dev",   # default; override for self-host or test
    timeout_s=30.0,               # per-request timeout
    retry=RetryConfig(...),       # see above
    http_client=httpx.Client(...) # advanced: BYO httpx.Client
)

The async client takes the same arguments; pass httpx.AsyncClient(...) instead of httpx.Client(...).

Development

# from packages/sdk-python/
python3.10 -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'
pytest
ruff check . && ruff format --check .
mypy src

Re-generate Pydantic models from a fresh OpenAPI spec:

# from the repo root
npm run sdk:python:dump-spec     # writes packages/sdk-python/openapi.json
npm run sdk:python:generate      # runs datamodel-codegen

Build the wheel:

# from packages/sdk-python/
python -m pip install build
python -m build       # → dist/driftstack-X.Y.Z-py3-none-any.whl + sdist

License

MIT.

Project details


Download files

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

Source Distribution

driftstack_sdk-0.1.3.tar.gz (16.6 kB view details)

Uploaded Source

Built Distribution

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

driftstack_sdk-0.1.3-py3-none-any.whl (21.9 kB view details)

Uploaded Python 3

File details

Details for the file driftstack_sdk-0.1.3.tar.gz.

File metadata

  • Download URL: driftstack_sdk-0.1.3.tar.gz
  • Upload date:
  • Size: 16.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for driftstack_sdk-0.1.3.tar.gz
Algorithm Hash digest
SHA256 a61b8f664242bda751532ab552689d1bcc749cb8a11f3305fe4310821d90938e
MD5 cd69eaaa95221847e8d1463d55f948a8
BLAKE2b-256 820c6105182c46eb99616ca4e6826026db879677c3c814faf707e5b8291aa68d

See more details on using hashes here.

File details

Details for the file driftstack_sdk-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: driftstack_sdk-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 21.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for driftstack_sdk-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 8d0628c2a38fa698485ebe5bb9c5e22a4588a16601dd951216c4800748c0da06
MD5 11840598a95c73035889d6c4739abd81
BLAKE2b-256 d2c0961a44901f12bcd415d1556943b7f8b418e9e528c35753e0574602597d7d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page