Generic API Integration Guide
This guide is for any external system that needs to query the Lumio catalog and inventory, purchase with a wallet, read service state and credentials, renew services, or perform lifecycle actions. Lumio exposes one generic API. Your system remains responsible for product mapping, end-customer orders, storefront UX, and the refund policy you offer end customers.
1. Before you integrate
The fixed API base URL is https://lumio.sh/api/v1/integration.
Create an API key under Account settings → API integrations. The full key is shown once; store it in a server-side secret manager.
Never put the key in a browser, mobile app, public repository, ordinary log, or end-customer message.
Grant only the scopes you need. Calls with purchase or renewal access charge the current Lumio wallet directly.
Amounts use minor currency units, so 12900 means USD 129.00. Timestamps use ISO 8601.
2. Scopes
catalog:read: catalog, billing-cycle prices, and exact inventory.
wallet:read: available wallet balance.
purchase:write: quotes and purchases.
service:read: purchase results, operations, and service state.
credentials:read: credentials for services that are ready.
renewal:write: wallet-funded renewals.
lifecycle:write: suspend, resume, terminate, reboot, reset password, and reinstall.
3. Authentication and connection test
Send Authorization: Bearer <Lumio API Key>, Accept: application/json, and a unique X-Request-Id on every request. Add Content-Type: application/json only when a JSON body is present.
curl -sS https://lumio.sh/api/v1/integration/account \
-H "Authorization: Bearer lumio_live_example.secret" \
-H "Accept: application/json" \
-H "X-Request-Id: partner-connection-0001"
HTTP 200 with code=200 confirms the connection. Save the returned scopes and verify that the next steps are authorized. Responses use the envelope {"code":200,"message":"...","data":{...}}. Branch on the HTTP status and data.error, not on the human-readable message.
4. Catalog, inventory, and wallet
Call GET /catalog/products for SKUs, cycles, prices, fixed configuration, and current inventory.
Use GET /catalog/products/{sku} for details. Submit only SKUs, cycles, configuration, and add-ons returned by the API.
Call GET /wallet before purchase and inspect available_cents. A storefront balance or cached value is not a substitute for the server-side check performed at purchase time.
5. Quote and purchase flow
Start with the read-only POST /purchases/quote. Do not send an Idempotency-Key for a quote:
{
"product_sku": "MAC-MINI-M4-ESSENTIAL",
"billing_cycle": "month",
"quantity": 1,
"configuration": {},
"addon_ids": []
}
After the end customer accepts the quote, generate and persist one stable external_reference and one stable Idempotency-Key. Return the quoted total_cents as expected_total_cents; this is the cost ceiling that prevents an unexpected charge after a price change.
POST /purchases
Idempotency-Key: partner-order-9001-create-v1
{
"external_reference": "partner-order-9001:create:1",
"product_sku": "MAC-MINI-M4-ESSENTIAL",
"billing_cycle": "month",
"quantity": 1,
"configuration": {},
"addon_ids": [],
"expected_total_cents": 12900
}
Persist the returned operation_id, Lumio order number, invoice number, and service ID immediately. If provisioning is still in progress, poll GET /operations/{operation_id} until status=succeeded, needs_attention, or a definitive failure. You can also recover the original purchase with GET /purchases/by-reference/{external_reference}.
A network timeout is not a purchase failure. Look up the external reference first. If it is not found, resend the exact same body with the same external_reference and Idempotency-Key. Never change the identifiers to bypass idempotency; doing so can create a duplicate purchase or charge.
6. Service state and credentials
GET /services/by-reference/{external_reference}: find a service from your purchase reference.
GET /services/{serviceId}: state, billing cycle, due date, and credential readiness.
GET /services/{serviceId}/credentials: call only after credentials_ready=true. Wait and retry when credentials are not ready; never fabricate local credentials.
Credentials are sensitive and may only be shown to an end customer or operator authorized for that service. Do not put them in ordinary logs. After termination or deletion, credentials are unavailable and next_due_at is null.
7. Renewal flow
Call GET /services/{serviceId}/renewal-quote and save current_next_due_at and total_cents.
Call POST /services/{serviceId}/renew with a stable renewal reference and idempotency key. Return the quote as expected_next_due_at and expected_total_cents.
Persist and poll the returned operation_id. Mark the external renewal complete only after the operation succeeds and the service due date has advanced.
{
"external_reference": "partner-service-1001:renew:2026-09-02",
"expected_next_due_at": "2026-09-02T00:00:00+00:00",
"expected_total_cents": 9900
}
8. Lifecycle and device actions
Every write below needs a stable external_reference and Idempotency-Key. Save the returned operation_id and poll it:
POST /services/{serviceId}/suspend: suspend the service.
POST /services/{serviceId}/resume: release the hold created by this API key. Billing or administrator holds can keep the service suspended.
POST /services/{serviceId}/actions/reboot: reboot the device.
POST /services/{serviceId}/actions/reset-password: ask Lumio to generate a password. Never submit a password; read credentials again after completion.
POST /services/{serviceId}/actions/reinstall: the body must include "confirmation":true. Reinstalling erases device data.
POST /services/{serviceId}/terminate: the body must include "immediate":true.
Termination is irreversible. A successful termination permanently releases service resources and credentials and forfeits the remaining paid period. Lumio does not automatically refund or credit the wallet. Refunding your end customer does not trigger a Lumio refund; exceptions require manual review by Lumio Support.
9. Errors, rate limits, and safe retry
400/422: correct the request or selection; do not retry unchanged forever.
401/403: stop and inspect the key, account state, and scopes.
404: verify that the resource belongs to the Lumio account behind this key.
409: resolve price, state, external-reference, or idempotency conflicts. Do not force a new identifier.
429, or 503 with Retry-After: wait for the specified delay and use exponential backoff.
When an operation enters needs_attention, stop automatic retries and retain the operation_id, X-Request-Id, external reference, and safe error code for an operator.
10. Go-live checklist
Production keys live only in server-side secret storage and have a tested rotation procedure.
SKUs, cycles, and fixed configuration come from the live catalog; purchase and renewal submissions include cost ceilings.
Every write persists its external reference and idempotency key before the request is sent.
Purchase, renewal, and lifecycle operations resume polling the original operation after a process restart.
Tests cover authentication failure, insufficient wallet balance, out of stock, price changes, rate limits, timeout, credentials not ready, and needs_attention.
The end-customer UX clearly explains wallet charges, reinstall data erasure, and immediate termination without an automatic refund.
11. Contract files and support
Sign in to Lumio, then open the API integrations page to download the OpenAPI contract and Postman collection. Treat OpenAPI as the field and state contract; use this article for the business flow.
When opening a support ticket, include the event time, endpoint, HTTP status, data.error, X-Request-Id, operation_id, and external reference. Never send a full API key, password, or service credential.