Metadata-Version: 2.5
Name: relyfinancials-sdk
Version: 0.1.0
Summary: Server-side Python SDK for Rely Identity, Organization, Billing, Wallet, Transactions, User, Inventory and POS APIs.
Project-URL: Documentation, https://github.com/killerbestshoot/rely/tree/main/packages/rely-sdk-python
Project-URL: Source, https://github.com/killerbestshoot/rely
License-Expression: LicenseRef-Proprietary
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Requires-Python: >=3.10
Requires-Dist: httpx<1,>=0.27
Description-Content-Type: text/markdown

# Rely Financials Python SDK

Server-side Python client for Rely Identity, organizations, branches and members, billing, wallet, transactions, inventory, and POS APIs. This package is released independently from the JavaScript SDK.

## Install

```bash
pip install relyfinancials-sdk
```

Python 3.10 or newer is required.

For local development from this monorepo, install the package in editable mode:

```bash
python -m pip install -e ./packages/rely-sdk-python
```

## Synchronous usage

```python
from rely_sdk import Rely, RelyAPIError

with Rely(client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET") as rely:
    try:
        checkout = rely.checkout.create({
            "amount": "25.00",  # decimal string, with up to two decimal places
            "currency": "USD",
            "destination_wallet_id": "wallet-id",
            "success_url": "https://merchant.example/paid",
            "cancel_url": "https://merchant.example/cancelled",
            "webhook_url": "https://merchant.example/webhooks/rely",
            "order_id": "order-123",
        })
        print(checkout)
    except RelyAPIError as exc:
        print(exc.status, exc.code, exc.request_id, str(exc))
```

## Asynchronous usage

```python
from rely_sdk import AsyncRely

async with AsyncRely(client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET") as rely:
    checkout = await rely.checkout.create({
        "amount": "25.00",
        "currency": "USD",
        "destination_wallet_id": "wallet-id",
        "success_url": "https://merchant.example/paid",
        "cancel_url": "https://merchant.example/cancelled",
        "webhook_url": "https://merchant.example/webhooks/rely",
    })
```

`AsyncRely` uses HTTPX's asynchronous client. Every network operation returns an awaitable.

## User and organization APIs

User and organization bearer tokens are passed explicitly to each method. Organization calls also take the organization ID first.

```python
with Rely() as rely:
    organizations = rely.organizations.list(access_token)
    branches = rely.branches.list(organization_id, access_token)

    # Named API domains retain the HTTP verb and route from the Rely API.
    products = rely.inventory.list_products(
        organization_id,
        access_token,
        query={"page": 1, "page_size": 25},
    )
    sale = rely.pos.create_sale(
        organization_id,
        access_token,
        body={"items": [{"variant_id": "variant-id", "quantity": 1}]},
    )
```

The grouped namespaces include `extensions`, `billing`, `wallet`, `transactions`, `user`, `inventory`, and `pos`. For registry-backed methods, pass path values as keyword arguments, and pass query or JSON data as `query=` or `body=`. For example:

```python
payment = rely.billing.payments.get_payment(access_token, payment_id="payment-id")
history = rely.wallet.get_history(access_token, query={"page": 1})
public_link = rely.billing.public.get_payment_link(token="public-token")
```

For a market POS scanner, send the decoded barcode as the `code` query value. The API resolves either a POS product or an inventory variant and returns the server-side price and stock details.

```python
item = rely.pos.lookup_catalog(
    organization_id,
    access_token,
    query={"code": scanned_code, "branch_id": branch_id},
)
```

JSON payloads use the API's snake_case field names. Call signatures for specialized helpers such as checkout, organizations, branches, members, invitations, and SDK tokens are exposed directly on those clients.

## Webhooks

Verify the signature against the exact raw request body before parsing or acting on an event. Do not parse and re-serialize the body before signature verification.

```python
from rely_sdk import construct_webhook_event

event = construct_webhook_event(raw_body, signature, webhook_secret)
# Deduplicate on event["event_id"] before processing.
```

The standalone `verify_webhook_signature(...)` helper returns `True` for a valid HMAC-SHA256 signature. Invalid signatures and invalid JSON raise `RelyWebhookSignatureError`.

## Configuration

`Rely` and `AsyncRely` accept `client_id`, `client_secret`, optional `api_base_url` and `auth_base_url`, `timeout` in seconds, `max_retries`, and `retry_base` in seconds. A single custom `api_base_url` is used for both gateways unless `auth_base_url` is also supplied. By default `/v1/identity/*` is routed to `https://auth.relyfinancials.cloud`; other API paths use `https://api.relyfinancials.cloud`.

Only GET requests are retried automatically (network errors, 429, and selected 5xx responses). Mutation calls are not retried to avoid duplicate charges or resource creation.

You can inject an existing `httpx.Client` or `httpx.AsyncClient` using `http_client=`. The SDK closes clients it creates itself; injected clients remain owned by the caller.

## Publishing

The GitHub Actions workflow builds and publishes this directory when a tag matching `rely-sdk-python-v*` is pushed. For token-based publishing, create a PyPI API token scoped to `relyfinancials-sdk`, then save it as the `PYPI_API_TOKEN` secret in the GitHub `pypi` environment. The workflow reads it as a secret and never writes it to the repository.
