Skip to main content

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.

Installation

pip install arcuserp
Requires Python 3.9 or later.

Quick start

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

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

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

# 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

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

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):
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.