Python SDK — crypto orders
The client.crypto_orders resource wraps every
customer-facing endpoint on the surface from both
Driftstack (sync) and AsyncDriftstack
(asyncio). Admin endpoints are not exposed; integrators that need
them call the REST surface directly.
Quote
from driftstack import Driftstack
client = Driftstack(api_key="ds_live_…")
quote = client.crypto_orders.quote({"product": "solo_manual"})
print(quote["price_cents"], quote["price_currency"]) Mint a checkout
Always pair the call with an idempotency_key so
accidental double-submits don't mint duplicate orders. The SDK
forwards it as the Idempotency-Key header; on a
duplicate key within the 24h window the server returns the
original order.
import uuid
key = str(uuid.uuid4())
order = client.crypto_orders.create_checkout(
{"product": "team_manual", "price_cents": 4900, "price_currency": "USD"},
idempotency_key=key,
)
print(order["order_id"], order["payment_address"]) List + drill down
# Newest-first; defaults to limit=50.
page = client.crypto_orders.list()
for o in page["orders"]:
print(o["order_id"], o["status"], o["expires_at"])
# Narrow to a single status server-side (V-666.BR).
paid = client.crypto_orders.list(status="paid", limit=25)
single = client.crypto_orders.get("ord_abc123def456")
print(single["events"]) # V-666.AU event timeline status accepts pending,
confirming, paid, failed,
partial, or cancelled. Unknown values
return a 400. limit is clamped to 1..=100.
Pagination — prefer iterate()
The iterate() helper walks every page until the
server stops emitting a next_cursor. Cursor handoff
is managed internally — do not pass
cursor= to iterate() (use
list() for an explicit page).
# Recommended: stream every paid order from the last 7d.
from datetime import datetime, timedelta, timezone
since = (datetime.now(timezone.utc) - timedelta(days=7)).isoformat()
for order in client.crypto_orders.iterate(
status="paid",
created_after=since,
limit=100,
):
print(order["order_id"])
# Or drive the cursor by hand:
cursor = None
while True:
page = client.crypto_orders.list(status="paid", cursor=cursor)
for o in page["orders"]:
print(o["order_id"])
cursor = page.get("next_cursor")
if cursor is None:
break Async parity
Every method on client.crypto_orders mirrors onto
AsyncDriftstack with async def;
iterate() returns an
AsyncIterator[dict] that you walk with
async for:
from driftstack import AsyncDriftstack
async def main():
async with AsyncDriftstack(api_key="ds_live_…") as client:
async for order in client.crypto_orders.iterate(status="paid"):
print(order["order_id"]) Update the customer note
client.crypto_orders.update_note("ord_abc", {"customer_note": "PO-9921"}) Cancel a pending order
from driftstack.errors import DriftstackError
try:
client.crypto_orders.cancel("ord_abc")
except DriftstackError as err:
# 409: order has moved past pending; cancellation is no longer self-service.
# 404: order doesn't exist or belongs to another account.
print(err.status, err.title) Crypto payments are non-refundable. Cancelling a pending order halts its pay window; cancelling a paid order is not supported — past billing periods stay billed. See /legal/refunds.
Fetch the receipt
receipt = client.crypto_orders.receipt("ord_abc")
print(receipt["paid_at"], receipt["price_cents"]) Listening for settlement
crypto.order.paid / crypto.order.failed
events are emitted server-side and are now subscribable — see
/docs/webhooks-crypto-events
for the payload contract. For integrations without an inbound
HTTPS endpoint, poll
client.crypto_orders.get(order_id) until
status transitions to paid or
failed. The Python SDK ships
verify_webhook_signature for every live event type,
including the now-live crypto.order.* events alongside the
session + quota + api-key + egress-capability event domains.
End-to-end example
A runnable end-to-end walkthrough ships with the SDK as
packages/sdk-python/examples/crypto_checkout.py.
Run with DRIFTSTACK_API_KEY=... python examples/crypto_checkout.py.