Python SDK

The official Python library for MOR API. Works with Python 3.8+ and supports both synchronous and asynchronous operations.

Installation

Install the SDK using pip:

pip install mor-sdk

Or with Poetry:

poetry add mor-sdk

Quick start

Initialize the client and create your first receipt:

from mor_sdk import MorClient

# Initialize with your API key
client = MorClient(api_key="sk_live_your_api_key")

# Create a receipt
receipt = client.receipts.create(
    items=[
        {
            "name": "Macchiato",
            "quantity": 2,
            "unit_price": 70.00,
            "tax_code": "STANDARD"
        }
    ],
    payment_method="ETHQR"
)

print(f"Receipt created: {receipt.fiscal_code}")

Configuration

You can configure the client in several ways:

from mor_sdk import MorClient

# Option 1: Pass API key directly
client = MorClient(api_key="sk_live_your_api_key")

# Option 2: Use environment variable (recommended for production)
# Set MOR_API_KEY in your environment, then:
client = MorClient()  # Automatically reads MOR_API_KEY

# Option 3: Full configuration
client = MorClient(
    api_key="sk_live_your_api_key",
    environment="production",  # or "sandbox"
    timeout=30,                # Request timeout in seconds
    max_retries=3,             # Auto-retry on transient errors
    device_id="dev_abc123"     # Default device for all receipts
)

Async support

For high-performance applications, we provide full async support:

import asyncio
from mor_sdk import AsyncMorClient

async def main():
    client = AsyncMorClient(api_key="sk_live_your_api_key")

    # Async receipt creation
    receipt = await client.receipts.create(
        items=[
            {"name": "Espresso", "quantity": 1, "unit_price": 50.00}
        ],
        payment_method="CASH"
    )

    # Batch operations are much faster with async
    tasks = [
        client.receipts.get(receipt_id)
        for receipt_id in receipt_ids
    ]
    receipts = await asyncio.gather(*tasks)

    await client.close()  # Don't forget to close the session

asyncio.run(main())

SDK Features

Automatic retries

Transient network errors are automatically retried with exponential backoff. No more failed receipts due to momentary connectivity issues.

Type safety

Full type hints throughout. Works great with IDEs like VS Code and PyCharm for autocomplete and error detection.

Idempotency

Pass an idempotency key to ensure operations are only processed once, even if you retry the request.

Debug logging

Enable debug mode to see detailed request/response logs. Perfect for troubleshooting integration issues.

Common operations

Receipts

# Create a receipt
receipt = client.receipts.create(items=[...], payment_method="CASH")

# Get a receipt by ID
receipt = client.receipts.get("rcpt_abc123")

# List receipts with filters
receipts = client.receipts.list(
    created_after="2026-01-01",
    payment_method="ETHQR",
    limit=50
)

# Create a credit note (refund)
credit_note = client.receipts.create(
    receipt_type="CREDIT_NOTE",
    original_receipt_id="rcpt_abc123",
    items=[...],
    reason="Customer return"
)

Devices

# Register a new device
device = client.devices.register(
    device_type="VFD",
    name="Cashier 1"
)

# List your devices
devices = client.devices.list()

# Get device status
device = client.devices.get("dev_abc123")

# Generate Z-Report for a device
z_report = client.devices.generate_z_report("dev_abc123")

Payments

# Create an ETHQR payment
payment = client.payments.create(
    amount=1250.00,
    method="ETHQR",
    reference="order_12345"
)

# Get QR code URL to display
print(payment.qr_code_url)

# Check payment status
payment = client.payments.get(payment.id)
if payment.status == "COMPLETED":
    # Create receipt
    receipt = client.receipts.create(...)

Error handling

The SDK raises specific exception types that you can catch and handle:

from mor_sdk import MorClient
from mor_sdk.exceptions import (
    MORAPIError,
    AuthenticationError,
    ValidationError,
    RateLimitError,
    DeviceError
)

client = MorClient(api_key="sk_live_your_api_key")

try:
    receipt = client.receipts.create(items=[...])
except AuthenticationError:
    # Invalid or expired API key
    print("Check your API key")
except ValidationError as e:
    # Invalid request parameters
    print(f"Validation failed: {e.message}")
    print(f"Field errors: {e.errors}")
except RateLimitError as e:
    # Too many requests
    print(f"Slow down! Retry after {e.retry_after} seconds")
except DeviceError as e:
    # Device-related issues
    print(f"Device error: {e.message}")
except MORAPIError as e:
    # Generic API error
    print(f"API error: {e.message}")

Framework integrations

Django

# settings.py
MOR_API_KEY = env("MOR_API_KEY")

# views.py
from django.conf import settings
from mor_sdk import MorClient

client = MorClient(api_key=settings.MOR_API_KEY)

def checkout(request):
    receipt = client.receipts.create(...)
    return JsonResponse({"fiscal_code": receipt.fiscal_code})

FastAPI

from fastapi import FastAPI, Depends
from mor_sdk import AsyncMorClient

app = FastAPI()

async def get_mor_client():
    client = AsyncMorClient()
    try:
        yield client
    finally:
        await client.close()

@app.post("/checkout")
async def checkout(client: AsyncMorClient = Depends(get_mor_client)):
    receipt = await client.receipts.create(...)
    return {"fiscal_code": receipt.fiscal_code}