Skip to main content

Python SDK for the Cyrus Payments API

Project description

cyrus-payments

Official Python SDK for the Cyrus Payments API — customer payment identity infrastructure built on Nomba. Give each of your customers a persistent identity and a dedicated virtual bank account, and let Cyrus handle provisioning, webhook reconciliation, and reporting.

This SDK covers the developer (API-key) surface only — customers, transactions, and payment events. It does not cover the merchant dashboard (JWT-authenticated) endpoints.

Installation

# uv (recommended)
uv add cyrus-payments

# pip
pip install cyrus-payments

Requires Python 3.10+.

Quick start

from cyrus import CyrusClient

client = CyrusClient(api_key="cyrus_live_xxx")

customer = client.customers.create(
    reference="cust_123",       # your own identifier for this customer (required)
    first_name="Ada",           # required
    last_name="Lovelace",       # optional
    email="ada@example.com",    # optional
)

print(customer.virtual_account.account_number, customer.virtual_account.bank_name)

Use it as a context manager to close the underlying HTTP connection pool automatically:

with CyrusClient(api_key="cyrus_live_xxx") as client:
    customer = client.customers.get("cust_123")

By default the client points at production (https://api.trycyrus.app). Override base_url for a local/staging backend:

client = CyrusClient(api_key="cyrus_test_xxx", base_url="http://localhost:8080")

Customers

# Create
customer = client.customers.create(reference="cust_123", first_name="Ada")

# Get
customer = client.customers.get("cust_123")

# Update profile (partial — only pass what's changing)
customer = client.customers.update("cust_123", first_name="Grace", phone_number="08012345678")

# KYC tier and status
from cyrus import KycTier, CustomerStatus

client.customers.set_kyc_tier("cust_123", tier=KycTier.TIER_2)
client.customers.suspend("cust_123")     # or .reactivate(...) / .close(...)

# Statement: identity + reporting summary + paginated transaction history
statement = client.customers.statement("cust_123", page=0, size=20)
print(statement.summary.lifetime_kobo, statement.summary.transaction_count)
for row in statement.transactions.content:
    print(row.ref, row.amount_kobo, row.match_status)

# Filter by date range and/or match status
from cyrus import MatchStatus

filtered = client.customers.statement(
    "cust_123",
    from_date="2025-01-01T00:00:00Z",
    to_date="2025-12-31T23:59:59Z",
    match_status=MatchStatus.DISCREPANCY,
)

Transactions

Merchant-wide transaction history, across all customers:

from cyrus import TransactionType, TransactionStatus, MatchStatus

page = client.transactions.list(
    customer_reference="cust_123",   # optional — omit to see all customers
    type=TransactionType.CUSTOMER_PAYMENT,
    status=TransactionStatus.SUCCESSFUL,
    match_status=MatchStatus.DISCREPANCY,
    from_date="2025-01-01T00:00:00Z",  # optional ISO-8601 instant
    to_date="2025-12-31T23:59:59Z",    # optional ISO-8601 instant
    page=0,
    size=20,
)
for txn in page:
    print(txn.reference, txn.amount_kobo, txn.fee_kobo)

transaction = client.transactions.get("txn_abc123")

Payment events (exception triage)

Raw inbound payment events, including orphaned/misdirected payments that couldn't be automatically attributed to a customer:

from cyrus import PaymentEventStatus

events = client.payment_events.list(status=PaymentEventStatus.IGNORED)
event = client.payment_events.get(str(events[0].id))

client.payment_events.replay(str(event.id))
client.payment_events.reattribute(str(event.id), customer_reference="cust_123")

Pagination

Every list endpoint returns a Page, which behaves like a list of the current page and also carries metadata:

page = client.customers.list(page=0, size=20)
list(page)                    # iterate current page's items
page.total_elements
page.total_pages
page.is_last

To walk every page automatically, use iter_all(...) (available on customers, transactions, and payment_events):

for customer in client.customers.iter_all(page_size=50):
    print(customer.reference)

Errors

All API errors raise a subclass of CyrusAPIError:

from cyrus import (
    CyrusAPIError,       # base class
    ValidationError,     # 400 — bad input; .field_errors has per-field details
    UnauthorizedError,   # 401 — missing/invalid API key
    NotFoundError,        # 404
    ConflictError,        # 409 — state conflict (e.g. customer already closed)
    ProviderError,        # upstream Nomba error
    ServerError,          # 5xx
)

try:
    client.customers.create(reference="cust_123", first_name="Ada", email="not-an-email")
except ValidationError as e:
    print(e.message, e.field_errors)
except CyrusAPIError as e:
    print(e.code, e.message, e.status_code)

Network-level failures (timeouts, connection errors) are retried automatically with exponential backoff (max_retries=3 by default, configurable on CyrusClient(...)).

Enums

Request/response fields backed by a fixed set of values are typed enums (CustomerStatus, KycTier, TransactionType, TransactionStatus, MatchStatus, PaymentEventType, PaymentEventStatus, ReconciliationFailureReason), all importable from the top-level cyrus package. Plain strings matching the same values also work, for callers that prefer not to import them:

# equivalent — both work
client.customers.set_status("cust_123", status=CustomerStatus.SUSPENDED)
client.customers.set_status("cust_123", status="SUSPENDED")

Full API reference

For the complete, always-current endpoint/schema/error reference, see the live Scalar docs: https://api.trycyrus.app/docs.

Development

cd sdk/python
uv sync --all-extras
uv run pytest -v

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

cyrus_payments-0.1.2.tar.gz (34.4 kB view details)

Uploaded Source

Built Distribution

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

cyrus_payments-0.1.2-py3-none-any.whl (16.0 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for cyrus_payments-0.1.2.tar.gz
Algorithm Hash digest
SHA256 8a9b7e53c47f16352f7d3d1613b7deaadc8ab820b188c8d54c5d55e88ba62925
MD5 3c46d43ff3d803514d30a96eb6ee3805
BLAKE2b-256 8b95fd5dfd3c5822e8cacfed59397e0297f66feb9801fa46013e311e00e4f918

See more details on using hashes here.

Provenance

The following attestation bundles were made for cyrus_payments-0.1.2.tar.gz:

Publisher: sdk-python-publish.yml on ojov/cyrus

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

File details

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

File metadata

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

File hashes

Hashes for cyrus_payments-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 976938579f08f3dba4e0f50f6dcce01b3997d82501b2969325506e5a376bc377
MD5 a468147154de8328df71f49a81f18947
BLAKE2b-256 247fd539ea4e7375a516dd45fb96a49a7e675c17e7e0f43abbd6422dd41f8e78

See more details on using hashes here.

Provenance

The following attestation bundles were made for cyrus_payments-0.1.2-py3-none-any.whl:

Publisher: sdk-python-publish.yml on ojov/cyrus

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