Quickstart
Verify a v1 key, create a partner and customer, then read usage and billing.
Create a partner and a customer, then read usage and billing. Base URL:
https://api2.smao.ai/api/distributor/v1.
1. Set up your key
SMAO issues your key and shows it only once. Keep it in a secret manager.
export SMAO_DISTRIBUTOR_KEY="your-v1-distributor-key"
export BASE="https://api2.smao.ai/api/distributor/v1"GET /health is public. All other endpoints require the Bearer token:
curl "$BASE/health"
curl "$BASE/plans" \
-H "Authorization: Bearer $SMAO_DISTRIBUTOR_KEY"Choose a plan slug and commitment from /plans for the customer request
below.
2. Create the partner (MSP)
curl -X POST "$BASE/partners" \
-H "Authorization: Bearer $SMAO_DISTRIBUTOR_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "MSP Hamburg GmbH",
"externalPartnerId": "MSP-001",
"contactEmail": "admin@msp.example",
"contactName": "Ada Admin",
"timezone": "Europe/Berlin"
}'Save both IDs from the response:
partner.idis thepartnerIdused for customer organizations.partner.organizationIdis the MSP's own internal SMAO organization.
A successful response means the partner and its organization exist. The trial and the invitation email are not guaranteed, so don't treat a received email as confirmation.
To keep the MSP's own organization in use after its trial, assign it a paid
plan. It is not reachable through the /organizations endpoints:
curl -X PATCH "$BASE/partners/665abc123def456789012345/plan" \
-H "Authorization: Bearer $SMAO_DISTRIBUTOR_KEY" \
-H "Content-Type: application/json" \
-d '{ "plan": { "slug": "advanced", "commitment": "monthly" } }'3. Create a customer organization
curl -X POST "$BASE/organizations" \
-H "Authorization: Bearer $SMAO_DISTRIBUTOR_KEY" \
-H "Content-Type: application/json" \
-d '{
"organization": {
"name": "Customer Hamburg GmbH",
"industry": "Manufacturing",
"timezone": "Europe/Berlin"
},
"owner": {
"email": "owner@customer.example",
"firstName": "Chris",
"lastName": "Customer"
},
"externalCustomerId": "CUST-4711",
"externalContractId": "CONTRACT-4711",
"partnerId": "665abc123def456789012345",
"plan": {
"slug": "business",
"commitment": "monthly"
}
}'Replace partnerId and the plan values with those returned by your calls. A
successful response includes the customer organization and its owner
invitation. The invitation email is not guaranteed.
externalPartnerId and externalCustomerId are reconciliation keys. If a
retry returns a duplicate-ID conflict, fetch the existing record instead of
creating a different identifier.
4. Read usage and billing
Usage query windows use inclusive YYYY-MM-DD dates and may cover up to 365
days. Neither from nor to may be after today (UTC), so a window for the
current month ends today, not on the last day of the month. A missing or
malformed date answers 400 VALIDATION_ERROR; an impossible calendar date,
from after to, a date after today, or a window over 365 days answers
400 INVALID_DATE_RANGE.
curl "$BASE/organizations/69c175970f3e28310926a1aa/usage?from=2026-07-01&to=2026-07-31" \
-H "Authorization: Bearer $SMAO_DISTRIBUTOR_KEY"
curl "$BASE/partners/665abc123def456789012345/usage?from=2026-07-01&to=2026-07-31" \
-H "Authorization: Bearer $SMAO_DISTRIBUTOR_KEY"Billing summaries are limited to 31 days (DATE_RANGE_TOO_LARGE; a window
over 365 days still answers INVALID_DATE_RANGE) and price usage against the
current assigned plan:
curl "$BASE/organizations/69c175970f3e28310926a1aa/billing-summary?from=2026-07-01&to=2026-07-31" \
-H "Authorization: Bearer $SMAO_DISTRIBUTOR_KEY"Monetary values are in the smallest unit of the returned currency (for example, cents for EUR). The API is polling-only; there are no Distributor webhooks.
Do not run create, update, plan-assignment, or delete examples against
live customer data as connectivity tests. Use /health, /plans, and read endpoints
for deployment verification.