Skip to main content

Official Python SDK for the OpenSettle API. Stablecoin billing on Base, Ethereum, Polygon, Arbitrum, Solana, and Tron.

Reason this release was yanked:

Response envelope unwrap bug — result.id was always None on create/retrieve/update. Upgrade to opensettle>=0.3.0.

Project description

opensettle

Official Python SDK for the OpenSettle API.

Non-custodial stablecoin billing on Base, Ethereum, Polygon, Arbitrum, Solana and Tron. Typed end-to-end, sync and async, signed-webhook verifier included, idempotent writes by default.

Install

pip install opensettle

Requires Python 3.9+.

Conventions

  • Method names are snake_case (Python idiom): os.customers.create(...).
  • Body fields and response keys are camelCase, matching the API's wire format exactly. Pass customerEmail=... not customer_email=.... Read result["createdAt"] not result["created_at"]. Zero translation, no surprises.

Quickstart

from opensettle import OpenSettle

os = OpenSettle(
    api_key="sk_test_…",      # or os.environ["OPENSETTLE_KEY"]
    workspace_id="ws_…",       # or os.environ["OPENSETTLE_WORKSPACE"]
)

# 1. Create a customer.
customer = os.customers.create(
    email="ada@example.com",
    name="Ada Lovelace",
    country="GB",
)
print(customer["id"])           # cus_…
print(customer["createdAt"])    # ISO-8601

# 2. Create a product + price.
product = os.products.create(name="Pro plan")
price = os.products.create_price(
    product["id"],
    amount=19_900,              # minor units
    currency="USD",
    interval="month",
)

# 3. Start a hosted-checkout subscription.
checkout = os.checkouts.create(
    mode="subscription",
    customerId=customer["id"],
    priceId=price["id"],
    chain="base",
    token="USDC",
    successUrl="https://merchant.com/ok",
    cancelUrl="https://merchant.com/cancel",
)
print(checkout["hostedUrl"])    # link to send the customer

Async

import asyncio
from opensettle import AsyncOpenSettle

async def main() -> None:
    async with AsyncOpenSettle(api_key="sk_test_…", workspace_id="ws_…") as os:
        customer = await os.customers.create(email="ada@example.com")
        print(customer["id"])

asyncio.run(main())

Webhooks

from opensettle import verify_webhook, WebhookVerificationError

@app.post("/webhooks/opensettle")
async def handler(request):
    raw = await request.body()
    try:
        event = verify_webhook(
            raw_body=raw,
            signature_header=request.headers.get("x-opensettle-signature"),
            secret=os.environ["WHSEC"],
        )
    except WebhookVerificationError as e:
        return Response(status=400, content=f"bad signature: {e.reason}")
    # event.data is the decoded JSON; event.timestamp is the signed epoch
    return Response(status=200)

Error handling

from opensettle import OpenSettle, RateLimitError, SettlementError

try:
    os.payments.refund("pay_…", amountMinor=500)
except RateLimitError as e:
    time.sleep(e.retry_after or 1)
    retry()
except SettlementError as e:
    if e.code == "insufficient_confirmations":
        wait_and_retry()

The full error hierarchy:

OpenSettleError
├── InvalidRequestError
├── InvalidStateTransitionError
├── AuthenticationError
├── ForbiddenError
├── NotFoundError
├── ConflictError
├── RateLimitError              # carries `retry_after: float | None`
├── SettlementError             # chain_reverted | insufficient_confirmations | signing_required
├── StepUpRequiredError         # aal_required
├── APIError                    # internal_error or forward-compat unknown codes
└── NetworkError                # transport-layer / timeout

Every error carries code, status, request_id, and param so you can quote the request ID in support tickets.

Configuration

os = OpenSettle(
    api_key="sk_test_…",
    workspace_id="ws_…",
    base_url="https://api.opensettle.io",   # default; override for self-host
    test_mode=None,                          # None | True | False env-assertion gate
    timeout=30.0,                            # seconds; default 30s
    max_network_retries=3,                   # 0 to disable retries
)

test_mode=True refuses sk_live_… keys; test_mode=False refuses sk_test_…. Leave None to accept either and let the API decide.

Resources

Resource Methods
customers list, retrieve, create, update, delete
products list, retrieve, create, update, list_prices, create_price, update_price, delete, delete_price
invoices list, retrieve, create, send, remind, void
payments list, retrieve, refund, refund_broadcast
subscriptions list, retrieve, create, pause, resume, cancel, change_plan
checkouts create, retrieve
webhook_endpoints list, retrieve, create, update, delete, rotate_secret, test

License

MIT — see LICENSE.

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

opensettle-0.2.0.tar.gz (40.0 kB view details)

Uploaded Source

Built Distribution

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

opensettle-0.2.0-py3-none-any.whl (29.1 kB view details)

Uploaded Python 3

File details

Details for the file opensettle-0.2.0.tar.gz.

File metadata

  • Download URL: opensettle-0.2.0.tar.gz
  • Upload date:
  • Size: 40.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for opensettle-0.2.0.tar.gz
Algorithm Hash digest
SHA256 338a9e50c90f8fcf64f2654a42b9b1b18502a480ad1b928e08dcbf71d1141579
MD5 b0c5ae60b8fc2981afb4a58a89776ed5
BLAKE2b-256 cc275bd8f128750bdb7315713f3306bbf98d5f16e7bfd17ad62731b5beb15c84

See more details on using hashes here.

Provenance

The following attestation bundles were made for opensettle-0.2.0.tar.gz:

Publisher: publish.yml on OpenSettle/opensettle-sdk-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file opensettle-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: opensettle-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 29.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for opensettle-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 583308f9e8195b82d3c83bde6a25c48d7b97d845650630b21c1ed888d5cc10c4
MD5 adf03f55d30bf4b4f28f1dc962af4e74
BLAKE2b-256 5d77d21bbf2b7f6206002ce897ed926790c7454b4fd1908411e8a3946c4027d3

See more details on using hashes here.

Provenance

The following attestation bundles were made for opensettle-0.2.0-py3-none-any.whl:

Publisher: publish.yml on OpenSettle/opensettle-sdk-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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