Skip to main content

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

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

import os
from opensettle import OpenSettle

client = OpenSettle(
    api_key=os.environ["OPENSETTLE_KEY"],
    workspace_id=os.environ["OPENSETTLE_WORKSPACE"],
)

# 1. Create a customer.
customer = client.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 = client.products.create(name="Pro plan")
price = client.products.create_price(
    product["id"],
    amount=19_900,              # minor units
    currency="USD",
    interval="month",
)

# 3. Start a hosted-checkout subscription.
checkout = client.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

Hosted checkout is EVM-only

The API accepts chain="solana" and chain="tron" on a checkout, and the chain reader will detect inbound SPL / TRC-20 deposits to verified wallets. However, the customer-facing hosted checkout page is currently EVM-only — Base, Ethereum, Polygon, and Arbitrum. Until Solana and Tron land in the hosted UI, drive those flows directly against /wallets + the chain reader rather than checkouts.create.

Async

import asyncio
from opensettle import AsyncOpenSettle

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

asyncio.run(main())

Webhooks

import os
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

import time
from opensettle import RateLimitError, SettlementError

try:
    client.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.5.1.tar.gz (47.8 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.5.1-py3-none-any.whl (33.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: opensettle-0.5.1.tar.gz
  • Upload date:
  • Size: 47.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for opensettle-0.5.1.tar.gz
Algorithm Hash digest
SHA256 2ec12883374f31f9af33f4f0152fccbcd2d4ed30338ff01d21af4c84c9a6720d
MD5 c3a4e2b8142b8da88b704d9ce76a31ef
BLAKE2b-256 33b46f13b12f8e860f67674fff0d648fb5fbd586e8051d9c515949b5a098194b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: opensettle-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 33.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for opensettle-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d93309b3b641f7667f3110faf2926940a5f0090d43db10e9ded8d73c21fff585
MD5 3f5bd07987a24caf8a3da86bae018a79
BLAKE2b-256 cd2a53bfc3c93ae8be750a6ab1ac70d6a3c87e67b135c3bd70bffea752a7d942

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