FastAPI Integration
Build a StableOps payment integration with FastAPI and the Python SDK, using sandbox orders, wallet instructions, and verified Webhooks for safe fulfillment.
Install
pip install stableops fastapi uvicorn python-dotenvConfigure
STABLEOPS_API_KEY=sk_sandbox_...
STABLEOPS_WEBHOOK_SECRET=whsec_...Create lib/stableops.py:
import os
from stableops import StableOps
stableops = StableOps(
api_key=os.environ["STABLEOPS_API_KEY"],
)The environment (sandbox / live) is determined by the API key prefix
(sk_sandbox_… / sk_live_…) — no extra parameter needed.
This guide uses a sandbox key and Base Sepolia. Import a base-sepolia receiving address in Sandbox and prepare test USDC first. For production, switch the API key, accepted mainnet assets, and Live address pool together; changing only the key is not enough.
These snippets omit business authentication. In production, authenticate the user, check order ownership, and load the payable amount from trusted server-side product or invoice records rather than accepting a client-supplied price. Authorize order retrieval and cancellation as well.
Create payment orders
from datetime import datetime, timedelta, timezone
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from lib.stableops import stableops
router = APIRouter()
class CreateOrderRequest(BaseModel):
merchant_order_id: str
amount: str
@router.post("/orders")
def create_order(input: CreateOrderRequest):
try:
# Auto-expire after 30 minutes; the order moves to `expired` and the address is released.
expires_at = (datetime.now(timezone.utc) + timedelta(minutes=30)).isoformat()
order = stableops.payment_orders.create(
merchant_order_id=input.merchant_order_id,
amount=input.amount,
accepted_assets=[{"chain": "base-sepolia", "asset": "USDC"}],
expires_at=expires_at,
)
return {
"id": order.id,
"status": order.status,
"amount": order.amount,
"payment_instructions": [
instruction.model_dump() for instruction in order.payment_instructions
],
}
except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc)) from excThe Python SDK sends the current payment-order payload and reuses
merchant_order_id as the Idempotency-Key header.
Verify webhooks
import json
import os
from fastapi import APIRouter, Header, Request, Response
from stableops.webhooks import SIGNATURE_HEADER, verify_webhook_signature
router = APIRouter()
@router.post("/webhooks/stableops")
async def stableops_webhook(
request: Request,
x_product_signature: str | None = Header(default=None, alias=SIGNATURE_HEADER),
):
raw_body = await request.body()
result = verify_webhook_signature(
body=raw_body,
header=x_product_signature,
secret=os.environ["STABLEOPS_WEBHOOK_SECRET"],
)
if not result.valid:
return Response(f"invalid signature: {result.reason}", status_code=400)
event = json.loads(raw_body)
if event["type"] == "payment.finalized":
payment_order_id = event["data"]["payment_order_id"]
# Fulfill after deduping X-Event-Id in your database.
return Response("ok")How is this guide?
Last updated
Express Integration
Integrate StableOps into Express with sandbox payment orders, server-side keys, raw-body Webhook verification, and idempotent processing for safe fulfillment.
Trading deposit monitoring
Monitor multi-chain deposits with StableOps payment orders, transfer instructions, verified Webhooks, idempotent ledger credit, and reorg recovery controls.