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.2.tar.gz (16.7 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.2-py3-none-any.whl (21.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: driftstack_sdk-0.1.2.tar.gz
  • Upload date:
  • Size: 16.7 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.2.tar.gz
Algorithm Hash digest
SHA256 bb6fee28cb74f1d5966accbe01163e2bb11c48d27ef957b6d7d2ff2c669d364d
MD5 63361c58ff07f92e420b66a0eb27ece6
BLAKE2b-256 7b86e756b5b7b89fbfc3de01e5728a5ee98831bffca7c4b7238bc31dcbc99b43

See more details on using hashes here.

File details

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

File metadata

  • Download URL: driftstack_sdk-0.1.2-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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 09cdd1b84c9c091b8d936cdbcbba613ec90b84ea283d054cac7bd194e4179e96
MD5 e549191d3f6bd52bc6a823ba2a850d68
BLAKE2b-256 7ef8a2b611e2d2b1f09ecf152dcbe31cd2b8a73c8b1425a2dc8d124c6dd53606

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