Authentication & Quotas
Authentication
Required Headers
Every API request must include two headers:
authorization: ApiKey YOUR_API_KEY
x-printago-storeid: YOUR_STORE_ID
authorization— your API key, prefixed withApiKey.x-printago-storeid— the ID of the organization (store) you are accessing. You can find this on the API Keys page.
Requests missing either header will receive a 401 Unauthorized response.
How Permissions Apply
An API key's effective permissions are the union of its directly assigned permissions and any permissions inherited from assigned roles. If a key attempts an action it does not have permission for, the request returns 403 Forbidden.
Full Access keys behave as Store Owner and can perform any action.
Rate Limits
API access is rate-limited across two sliding windows:
| Window | Limit |
|---|---|
| Per minute | 60 requests |
| Per hour | 600 requests |
When you exceed a limit, requests return HTTP 429 Too Many Requests until the window resets. The response includes a Retry-After header indicating how long to wait.
If these limits are too restrictive for your use case, contact us to discuss higher quotas.
Real-time Data with MQTT
For real-time printer updates, Printago provides MQTT access. This is the same data stream that powers the Printago web dashboard — giving you immediate access to printer states, temperatures, progress, and more.
Connection Details
| Setting | Value |
|---|---|
| MQTTS | mqtts://realtime.printago.io:8883 |
| MQTT over WebSockets | wss://realtime.printago.io:9001 |
| Username | Your store ID |
| Password | Your API key |
| Client ID | apiclient_{keyId}_{suffix} — see below |
MQTT Client ID
Your MQTT Client ID must follow the format apiclient_{keyId}_{suffix}, where:
keyIdis the first 24 characters of your API key (this is the Key ID shown on the API Keys page).suffixmust be unique per client instance. Generate a random value once when your application starts, then reuse it for that client's lifetime — including across reconnects. Do not hard-code a fixed string such as your app name, hostname, or store ID, and do not generate a new one on every reconnect.
For example, if your API key is abc123def456ghi789jkl012secret..., your Client ID would be something like apiclient_abc123def456ghi789jkl012_k4p2xr9d.
// Generate once at startup, not per connection attempt.
const suffix = Math.random().toString(36).slice(2, 10);
const clientId = `apiclient_${KEY_ID}_${suffix}`;
If you run multiple processes, containers, or replicas against the same API key, each one needs its own suffix.
MQTT requires client IDs to be unique across the broker. If two connections use the same Client ID, the broker disconnects the older one, which typically reconnects and disconnects the newer one, producing an endless reconnect loop. That loop re-delivers your full topic state on every cycle, so it burns bandwidth on both ends and can get your integration rate-limited. Re-using a static suffix across processes, containers, replicas, or browser tabs is the usual cause.
The Key ID is also available on the API Keys page — click the copy button next to any key to copy it.
Subscription Topics
All topics are namespaced under your store ID. Replace {storeId} with your store ID (the same value you use for the MQTT username).
| Topic | Description |
|---|---|
stores/{storeId}/printer-stats/# | Real-time temperature, progress, and state updates for each printer |
stores/{storeId}/entities/# | Entity change events for every entity type |
stores/{storeId}/entities/{entityType} | Entity change events for a single entity type (see below) |
Subscriptions are filtered by your API key's permissions — you only receive events for entity types your key is allowed to view.
The broker caches each key's topic access, so granting or removing a permission on a key used for MQTT can take up to 6 hours to take effect. Disconnecting and reconnecting the client does not clear the cache. Deactivating or deleting a key blocks new connections within about an hour.
Entity Change Events
Entity change events fire whenever an entity is created, updated, or deleted. Subscribe to stores/{storeId}/entities/# for all changes, or to stores/{storeId}/entities/{entityType} for a specific type. Each message payload includes the action (INSERT, UPDATE, or DELETE), the affected entities, and, for updates, a changes map of the fields that changed.
The following entity types are published:
addon_subscriptions | addon_usage_records | api_keys |
cost_components | customers | entitlements |
folders | ignored_skus | integrations |
maintenance_completion_logs | maintenance_items | material_group_members |
material_groups | material_profile_assignments | material_variants |
materials | order_items | orders |
part_build_steps | part_builds | part_material_assignments |
parts | print_jobs | printer_maintenance_enrollments |
printer_slots | printer_throttle_group_members | printer_throttle_groups |
printer_throttle_leases | printers | profiles |
settings_notifications | settings_store | sku_builds |
sku_costs | sku_option_bindings | sku_option_properties |
sku_option_property_values | sku_option_value_filters | sku_option_values |
sku_options | sku_parts | skus |
slicer_jobs | subscriptions | user_permissions |
See the API Keys page in the Printago app for interactive examples.
Swagger / OpenAPI Specification
The most current API specification is always available from the API Keys page via the Download Swagger JSON button, or directly at:
- Download OpenAPI/Swagger Specification — OpenAPI 3.1 format
You can import this specification into tools like:
- Swagger Editor
- Postman
- Insomnia
- Any OpenAPI-compatible tool
Need help? Join our Discord community for support!