> ## Documentation Index
> Fetch the complete documentation index at: https://docs.arcuserp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Python SDK

> Official Python client for the Arcus ERP API.

## Installation

```bash theme={null}
pip install arcuserp
```

Requires Python 3.9 or later.

## Quick start

```python theme={null}
import os
from arcuserp import Arcus

arcus = Arcus(
    api_key=os.environ['ARCUS_API_KEY'],
    entity_id=os.environ['ARCUS_ENTITY_ID'],
)

# List accounts
accounts = arcus.accounts.list(limit=10)
for account in accounts.data:
    print(account.name)

# Create a sales order
import uuid

order = arcus.orders.create(
    {
        'document_type': 'sales_order',
        'account_id': 'acc_01H...',
        'line_items': [
            {'product_id': 'prod_01H...', 'quantity': 5, 'unit_price': 29.99}
        ],
    },
    idempotency_key=str(uuid.uuid4()),
)
print(order.id)
```

## Configuration

```python theme={null}
from arcuserp import Arcus

arcus = Arcus(
    api_key=os.environ['ARCUS_API_KEY'],
    entity_id=os.environ['ARCUS_ENTITY_ID'],

    # Optional
    base_url='https://api.arcuserp.com/v1',  # optional; defaults to https://api.arcuserp.com/v1
    arcus_version='2026-05-01',                   # API version
    max_retries=3,                                # default: 2
    timeout=30,                                   # seconds; default: 30
)
```

## Async support

```python theme={null}
import asyncio
from arcuserp import AsyncArcus

async def main():
    arcus = AsyncArcus(
        api_key=os.environ['ARCUS_API_KEY'],
        entity_id=os.environ['ARCUS_ENTITY_ID'],
    )
    async with arcus as client:
        accounts = await client.accounts.list(limit=10)
        for account in accounts.data:
            print(account.name)

asyncio.run(main())
```

## Auto-pagination

```python theme={null}
# Synchronous auto-paginate
for order in arcus.orders.list(limit=100):
    process_order(order)

# Async auto-paginate
async for order in arcus.orders.list(limit=100):
    await process_order(order)
```

## Error handling

```python theme={null}
from arcuserp import ArcusAPIError, ArcusRateLimitError

try:
    order = arcus.orders.retrieve('ord_invalid')
except ArcusRateLimitError as e:
    # SDK auto-retries 429s; you only see this after max_retries exhausted
    print('Rate limit exhausted after retries')
except ArcusAPIError as e:
    print(e.code)       # machine-readable code
    print(e.hint)       # human-readable hint
    print(e.request_id) # for Arcus support
    print(e.status)     # HTTP status
```

## Webhooks

```python theme={null}
from flask import Flask, request, jsonify
from arcuserp import Arcus, ArcusWebhookError

app = Flask(__name__)
arcus = Arcus(api_key=os.environ['ARCUS_API_KEY'], entity_id=os.environ['ARCUS_ENTITY_ID'])

@app.route('/webhook', methods=['POST'])
def webhook():
    try:
        event = arcus.webhooks.construct_event(
            payload=request.data,
            sig_header=request.headers.get('Arcus-Signature'),
            secret=os.environ['ARCUS_WEBHOOK_SECRET'],
        )
    except ArcusWebhookError as e:
        return str(e), 400

    if event.type == 'order.confirmed':
        print('Order confirmed:', event.data.object.id)
    elif event.type == 'payment.received':
        print('Payment received:', event.data.object.id)

    return jsonify({'received': True})
```

## Type hints

The SDK ships full type hints (PEP 484):

```python theme={null}
from arcuserp.types import Order, Account, ArcusListResponse

def process_order(order: Order) -> None:
    print(order.document_type)  # Literal['quote', 'sales_order', 'invoice', ...]
    print(order.status)         # Literal['draft', 'confirmed', 'fulfilled', ...]
```

## Source

Generated from `arcus-api-core/openapi/arcus-api-v1.yaml` via Speakeasy. Source: [arcus-erp-aws/sdks/python](https://github.com/reubenbroussard/arcus-erp-aws/tree/main/sdks/python).
