Appearance
Requests and errors
Requests
GETreads,POSTadds or runs an action (/devices/{id}/renew),PATCHchanges,DELETEdeletes. Another method on a path answers405.- Send JSON with
Content-Type: application/json. Answers are JSON. - Times are UTC in ISO 8601:
2026-11-17T19:00:00Z. Filters also accept a date:2026-11-17. PATCHchanges only the fields you send.- Adding answers
201with the new record, deleting204with no body.
Lists and paging
A list answers:
json
{ "data": [ { "id": 41 }, { "id": 40 } ], "next_cursor": "NDA" }Newest first. ?limit= sets how many (50 by default, at most 100). For the next page, send the answer's next_cursor as ?cursor=, until it is null:
sh
curl "https://panel.example.com/api/rest/v1/devices?limit=100" -H "Authorization: Bearer mtx_your_key"
curl "https://panel.example.com/api/rest/v1/devices?limit=100&cursor=NDA" -H "Authorization: Bearer mtx_your_key"Records added while you page do not shift the pages.
Errors
Every refusal has the same shape:
json
{
"error": "insufficient_credit",
"message": "Berlin TV does not have enough credits (balance 10)."
}error is for your program; message is for people and logs and may change. Invalid input (422) also lists the fields:
json
{
"error": "invalid",
"message": "The input is not valid.",
"fields": { "email": ["The email field must be a valid email address."] }
}| Status | error | Meaning | What to do |
|---|---|---|---|
| 401 | invalid_key | No key, or unknown, revoked or expired, or its account is switched off | Check the key |
| 403 | ip_not_allowed | The key may not be used from this address | Add the address to the key |
| 403 | read_only | A read key sent something other than GET | Use a key with write access |
| 403 | forbidden | The key's account may not do this | Ask an administrator |
| 404 | not_found | No such path, or no such record this key may reach | Check the id |
| 405 | method_not_allowed | Wrong method for the path | |
| 409 | insufficient_credit | The reseller has too few credits for the plan | Top up, then retry |
| 409 | device_limit | The reseller's device limit is reached | |
| 409 | license_limit | The Mintrix license's device limit is reached | |
| 409 | already_exists | A device with this MAC or login exists | Look it up with ?mac= |
| 409 | has_devices | The subscriber still has devices | Delete or move them first |
| 409 | idempotency_mismatch | The Idempotency-Key was used for another request | Use a new key |
| 409 | idempotency_in_progress | The first request with this Idempotency-Key is still running | Retry shortly |
| 422 | invalid | Invalid input; see fields | Fix the input |
| 429 | too_many_requests | More than 120 requests this minute | Wait the Retry-After seconds |
| 500 | server_error | A fault in Mintrix; it is logged | Retry later |
| 502 | ministra_failed | Ministra refused the change; nothing changed in Mintrix | Retry later, or see message |
| 503 | unavailable | Mintrix cannot serve now (license or maintenance) | Retry later |
Retrying safely
Adding a device and renewing one cost credit. Networks fail: your system may not get the answer and send the request again. To make that safe, send an Idempotency-Key header with a value unique to the order, e.g. your invoice number:
sh
curl -X POST https://panel.example.com/api/rest/v1/devices/41/renew \
-H "Authorization: Bearer mtx_your_key" \
-H "Idempotency-Key: invoice-10042"Within 24 hours, the same key with the same request returns the first answer again, with the header Idempotent-Replayed: true, and charges nothing more. The same key with a different request answers 409 idempotency_mismatch.
A request that failed with 5xx is not remembered: retry it with the same key.
Always send one
Send an Idempotency-Key with every POST /devices and POST /devices/{id}/renew. It costs nothing and protects your customers from double charges.
Rate
Each key may make 120 requests a minute. Beyond that, Mintrix answers 429 with a Retry-After header in seconds. Page with ?limit=100 to read many records in few requests.