Skip to content

Quick start (15 minutes)

Start here

You will run a mock AIOTIC tenant, a receive endpoint with the SDK's validation pipeline, upload an order, and watch it flow into a (demo) ERP. Nothing here touches a real tenant.

Prerequisites

Python 3.11+ and pip (or uv). No AIOTIC account needed for this exercise.

1. Install the SDK

bash
python -m venv .venv && source .venv/bin/activate
pip install "aiotic-sdk[all]"
bash
uv venv && source .venv/bin/activate
uv pip install "aiotic-sdk[all]"

2. Start a mock tenant

bash
aiotic mock
# Mock AIOTIC tenant on http://localhost:8080
# keys: mock-integration-key (all endpoints), mock-sync-key (master data only)

The mock implements the public API with realistic behaviour: uploads move through WaitingProcessingProcessed in a few seconds, a file name containing attention produces an Attention order with an unresolved article, fail produces Failed, and /erp/send really calls your endpoint.

3. Bootstrap your service

In a second terminal:

bash
aiotic init            # answers: base URL http://localhost:8080, key mock-integration-key
aiotic doctor

init writes a .env (base URL, keys, a freshly generated AIOTIC_ERP_RECEIVE_KEY) and a service.py. doctor checks connectivity, both keys and whether master data is present:

┃ check                          ┃ result                          ┃
│ GET /healthcheck               │ OK ok                           │
│ GET /order_status/list (key)   │ OK 0 orders                     │
│ master data: customers         │ OK 1 records                    │
│ master data: products          │ OK 3 records                    │

4. Run the receive endpoint

bash
aiotic serve           # http://localhost:9000  (POST /aiotic/orders, /aiotic/processing, /erp/events)

service.py is three lines — the in-memory demo ERP behind the default pipeline:

python
from aiotic.service import build_app
from aiotic.erp.memory import InMemoryErp   # replace with your adapter later

app = build_app(erp=InMemoryErp())

Tell the mock tenant where your endpoint lives (in production you give this to the AIOTIC team; the mock has a helper):

bash
curl -X POST localhost:8080/_mock/config -H 'Content-Type: application/json' \
  -d "{\"erp_url\": \"http://localhost:9000/aiotic/orders\", \"erp_key\": \"$(grep AIOTIC_ERP_RECEIVE_KEY .env | cut -d= -f2)\"}"

5. Upload an order and send it

bash
echo "fake pdf" > PO-4711.pdf
aiotic orders upload PO-4711.pdf
# uploaded → request_id 7f0c…   then:  7f0c…: PROCESSED — PO-4711, 2 lines

aiotic orders send 7f0c…
# sent — ERP reference SO-1000

What happened, in sequence:

Rendering diagram…

The mock did what a real tenant does: locked the order, POSTed it to your endpoint with the key, read success, stored the ERP reference.

6. See a rejection

bash
echo "x" > PO-4712-attention.pdf
aiotic orders upload PO-4712-attention.pdf      # → ATTENTION (one line has no article number)
aiotic orders send <request_id>
# ERP error: Line 3 has no article number (items[2].article_number)

The pipeline rejected the order before it reached the ERP, and the message is exactly what an operator would see in the AIOTIC app. Change service.py to use DataApiAdapter (a SQLite demo ERP with only tables) and you will see why that matters:

python
from aiotic.service import build_app
from aiotic.erp.data_api import DataApiAdapter, sqlite_demo

app = build_app(erp=DataApiAdapter(sqlite_demo("erp-demo.db")))

Where to go next

Documentation revision 3 · Published 8 September 2026 · commit 6862d5e. Verified against AIOTIC API v1.0.0. AIOTIC is a product of DevOps Company.