{ "openapi": "3.1.0", "info": { "version": "1.2.0", "title": "Navixy Admin Panel API", "summary": "API calls for dealer, reseller, and account administration", "description": "This is an API reference for the Navixy Admin Panel API. Use these endpoints to authenticate a dealer session, read dealer information, manage activation codes, and read or update panel service, notification, and branding settings.\n\nThis specification covers every documented Admin Panel API resource family.\n\n**Parameters.** All parameters are documented in the JSON request body. The API also accepts the same parameters as form-encoded body fields or as query-string parameters, but those forms are not documented per operation. See the authentication guide for details.\n\n**Errors.** Detect an error by checking the HTTP status code: anything other than `200 OK` carries an error body with `success: false` and a `status.code` giving the API-level error code. The default error status is `400`, with some codes mapping to `402`, `403`, `404`, `409`, or `500`. Validation failures also include an `errors` array naming the offending parameter.", "contact": { "name": "Navixy support", "email": "support@navixy.com", "url": "https://www.navixy.com/contact/" }, "license": { "name": "Apache 2.0", "identifier": "Apache-2.0" } }, "servers": [ { "url": "https://api.eu.navixy.com/v2", "description": "Navixy production server on European platform" }, { "url": "https://api.us.navixy.com/v2", "description": "Navixy production server on American platform" }, { "url": "https://api.me.navixy.com/v2", "description": "Navixy production server on Middle East platform" } ], "tags": [ { "name": "Account", "description": "Operations for authenticating a dealer into the Admin Panel, inspecting the permissions granted to the current session, and ending that session. All resources under the /panel/account/ path." }, { "name": "Dealer", "description": "Operations for reading dealer information, managing activation codes, changing the dealer password, and reading or updating panel settings covering service configuration, notification originators, and branding images. All resources under the /panel/dealer/ path." }, { "name": "Gateways", "description": "Email gateways a dealer can send notification mail through, either owned by the dealer or leased from the platform owner. All resources under the /panel/gateways/ path." }, { "name": "Order", "description": "Equipment orders placed by the dealer. All resources under the /panel/order/ path." }, { "name": "Subpaas", "description": "Sub-dealers, also called Sub-PaaS accounts: dealers operating underneath another dealer. Covers listing, reading, creating and updating them, changing their password, and opening a session as one. All resources under the /panel/subpaas/ path." }, { "name": "Tariff", "description": "Service plans a dealer offers to its users, and the per-device-type defaults applied on device registration. Called plans in the interface and tariffs in the API paths. All resources under the /panel/tariff/ path." }, { "name": "Timezone", "description": "The platform-wide list of supported time zones. All resources under the /panel/timezone/ path." }, { "name": "Tracker", "description": "Devices belonging to the dealer, their clones, settings, and plans. All resources under the /panel/tracker/ path." }, { "name": "User", "description": "End users belonging to the dealer: their profiles, sessions, balance transactions, menu presets, and multi-factor authentication settings. All resources under the /panel/user/ path." } ], "paths": { "/panel/account/auth": { "post": { "tags": [ "Account" ], "summary": "Authenticate dealer", "description": "Authenticate a dealer into the Admin Panel and obtain a session hash. This is the only Admin Panel operation that requires no existing session and no permissions. The returned hash is the credential for every other operation, and the response also reports the full permission set granted to the session, so a client can discover what it is allowed to do without a second call.", "operationId": "accountAuth", "security": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "login", "password" ], "properties": { "login": { "type": "string", "description": "The panel login. Numeric in Navixy-hosted installations.", "example": "20410" }, "password": { "type": "string", "description": "The panel password.", "format": "password", "example": "12f@14Y$" } } } } } }, "responses": { "200": { "description": "Session created", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "hash": { "type": "string", "description": "The session key. Pass it in the `Authorization` header as `NVX ` on all subsequent requests.", "readOnly": true, "example": "fa7bf873fab9333144e171372a321b06" }, "permissions": { "$ref": "#/components/schemas/PanelPermissions" } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Access denied, error code 11: the dealer is blocked", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/account/get_permissions": { "post": { "tags": [ "Account" ], "summary": "Get account permissions", "description": "Return the permission set granted to the current panel session. Takes no parameters beyond the session credential. Use it to re-check permissions without re-authenticating, for example after a dealer's permissions have been changed by the platform owner.", "operationId": "accountGetPermissions", "responses": { "200": { "description": "Permissions of the current session", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "permissions": { "$ref": "#/components/schemas/PanelPermissions" } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/account/logout": { "post": { "tags": [ "Account" ], "summary": "Log out", "description": "End the current panel session. The session hash is invalidated immediately and cannot be reused: any subsequent request with it, including another logout, fails with error code 4. Takes no parameters beyond the session credential.", "operationId": "accountLogout", "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/dealer/get_info": { "post": { "tags": [ "Dealer" ], "summary": "Get dealer info", "description": "Read information about the authorized dealer: PaaS plan and its service prices, balance, active tracker counts and limits, branding paths, block status, enabled features, and defaults applied to newly created users. Takes no parameters beyond the session credential. Note that the dealer fields are returned at the top level of the response rather than nested under a `value` key.", "operationId": "dealerGetInfo", "responses": { "200": { "description": "Dealer information", "content": { "application/json": { "schema": { "allOf": [ { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true } } }, { "$ref": "#/components/schemas/Dealer" } ] } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/dealer/activation_code/create": { "post": { "tags": [ "Dealer" ], "summary": "Create activation codes", "description": "Create a batch of activation codes bound to a plan. Activation codes let an end user register a device themselves and have it configured with the correct plan, bonus balance, and free period from the start. The plan referenced by `tariff_id` must belong to the current dealer. Returns the number of codes actually created, which can be lower than requested.", "operationId": "dealerActivationCodeCreate", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "count", "tariff_id", "bonus_amount", "free_days" ], "properties": { "count": { "type": "integer", "description": "Number of codes to create.", "example": 10, "minimum": 1 }, "tariff_id": { "type": "integer", "description": "ID of the plan the new codes apply. Must belong to the current dealer.", "example": 12457 }, "bonus_amount": { "type": "integer", "description": "Bonus amount added to the user's balance when a device is activated with one of these codes.", "example": 3 }, "free_days": { "type": "integer", "description": "Number of free days granted on activation.", "example": 5, "minimum": 0 } } } } } }, "responses": { "200": { "description": "Codes created", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "count": { "type": "integer", "description": "Number of codes actually created.", "readOnly": true, "example": 10 } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/dealer/activation_code/list": { "post": { "tags": [ "Dealer" ], "summary": "List activation codes", "description": "List the current dealer's activation codes, with optional text filtering, ordering, and pagination. When `filter` is used, a code is returned only if the filter string matches one of `code`, `tariff_id`, `device_id`, or `device_type`. Every parameter is optional; calling with no parameters returns the unfiltered list.", "operationId": "dealerActivationCodeList", "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object", "properties": { "filter": { "type": "string", "description": "Text filter. Matched against `code`, `tariff_id`, `device_id`, and `device_type`.", "example": "5248654776" }, "order_by": { "type": "string", "description": "Field to order the list by.", "enum": [ "code", "activated", "tariff_id", "tariff_name", "device_type", "money_amount", "bonus_amount", "free_days" ], "example": "code" }, "ascending": { "type": "boolean", "description": "Order direction. Ascending when `true`, descending otherwise.", "default": true }, "offset": { "type": "integer", "description": "Starting offset, for pagination.", "default": 0 }, "limit": { "type": "integer", "description": "Maximum number of records to return, for pagination.", "example": 50 } } } } } }, "responses": { "200": { "description": "Activation codes", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "list": { "type": "array", "description": "The matching activation codes.", "readOnly": true, "items": { "$ref": "#/components/schemas/ActivationCode" } }, "count": { "type": "integer", "description": "Total number of matching records, ignoring `offset` and `limit`.", "readOnly": true, "example": 1 } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/dealer/activation_code/update": { "post": { "tags": [ "Dealer" ], "summary": "Update activation codes", "description": "Change the plan, bonus amount, and free period on a set of existing activation codes. A code is updated only if it is listed in `codes`, belongs to the current dealer, has not been activated yet, and has the same `device_type` as the new plan. Returns the number of codes actually updated, which can be lower than the number supplied.", "operationId": "dealerActivationCodeUpdate", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "codes", "tariff_id", "bonus_amount", "free_days" ], "properties": { "codes": { "type": "array", "description": "Codes to update.", "items": { "type": "string" }, "example": [ "12315124", "12451576" ], "minItems": 1 }, "tariff_id": { "type": "integer", "description": "ID of the new plan. Must belong to the current dealer.", "example": 12457 }, "bonus_amount": { "type": "integer", "description": "New bonus amount.", "example": 3 }, "free_days": { "type": "integer", "description": "New free period, in days.", "example": 5, "minimum": 0 } } } } } }, "responses": { "200": { "description": "Codes updated", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "count": { "type": "integer", "description": "Number of codes actually updated.", "readOnly": true, "example": 5 } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/dealer/password/update": { "post": { "tags": [ "Dealer" ], "summary": "Update dealer password", "description": "Change the password of the authorized dealer.\n\n**All panel sessions for this dealer are deleted on success, including the one making the request.** The session hash stops working immediately and you must authenticate again to continue.\n\nThe new password must differ from the current one, must satisfy the dealer's complexity rules, and must not match any recently used password. The enforced rules are returned as `password_policy` by the dealer get info operation. Both values are trimmed and must contain printable characters only.", "operationId": "dealerPasswordUpdate", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "old_password", "new_password" ], "properties": { "old_password": { "type": "string", "description": "Current dealer password. Trimmed before comparison; printable characters only.", "format": "password", "example": "qwerty" }, "new_password": { "type": "string", "description": "New dealer password. Must differ from the current one, satisfy the dealer's password policy, and not match a recently used password.", "format": "password", "example": "Hh6FXTt%E!Rx*%f3" } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/dealer/settings/image/upload": { "post": { "tags": [ "Dealer" ], "summary": "Upload branding image", "description": "Upload a branding image of the given type. Unlike every other Admin Panel operation, this one requires a `multipart/form-data` request, with the image supplied as a part named `file`. Branding must be enabled for the dealer's plan.\n\n`type` must be sent as a form part. Supplying it as a query parameter instead fails with error code 234.\n\nThe session credential travels in the `Authorization` header here exactly as it does on the JSON operations.\n\nIf `redirect_target` is supplied, the API answers `302` with a `Location` of `?response=` instead of returning the JSON body directly.", "operationId": "dealerSettingsImageUpload", "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "type": "object", "required": [ "type", "file" ], "properties": { "type": { "$ref": "#/components/schemas/BrandingImageType" }, "file": { "type": "string", "format": "binary", "description": "The image file. Its MIME type must be one of `image/jpeg`, `image/pjpeg`, `image/png`, `image/gif`, `image/webp`, or `image/x-icon`. Use `image/x-icon` for the favicon type." }, "redirect_target": { "type": "string", "description": "Optional URL to redirect to instead of returning the JSON response body.", "format": "uri", "example": "https://demo.navixy.com/branding" } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "302": { "description": "Returned instead of `200` when `redirect_target` is supplied. The `Location` header is `?response=`." }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "402": { "description": "Feature unavailable, error code 236: branding is disabled by the dealer plan", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/dealer/settings/image/delete": { "post": { "tags": [ "Dealer" ], "summary": "Delete branding image", "description": "Delete the branding image of the given type. The dealer's interface falls back to the platform default for that element.", "operationId": "dealerSettingsImageDelete", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "type" ], "properties": { "type": { "$ref": "#/components/schemas/BrandingImageType" } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/dealer/settings/notification/read": { "post": { "tags": [ "Dealer" ], "summary": "Read notification settings", "description": "Read the current dealer's notification settings: the originators used when the platform sends email, SMS, and voice notifications to that dealer's end users. Takes no parameters beyond the session credential.", "operationId": "dealerSettingsNotificationRead", "responses": { "200": { "description": "Notification settings", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "value": { "$ref": "#/components/schemas/NotificationSettings" } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/dealer/settings/notification/update": { "post": { "tags": [ "Dealer" ], "summary": "Update notification settings", "description": "Update the current dealer's notification settings.\n\n**This is a full replacement, not a partial update.** Any writable field you omit is reset to its default rather than left alone. Omitting the optional `email_special`, for example, clears it. Always read the current settings first, change what you need, and send the complete object back.\n\n`email_from`, `email_footer`, `sms_originator`, and `caller_id` are mandatory on every call. Omitting any of them fails with error code 7 and an `errors` array naming the missing field.", "operationId": "dealerSettingsNotificationUpdate", "requestBody": { "required": true, "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/NotificationSettings" }, { "type": "object", "required": [ "email_from", "email_footer", "sms_originator", "caller_id" ] } ] } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/dealer/settings/service/read": { "post": { "tags": [ "Dealer" ], "summary": "Read service settings", "description": "Read the current dealer's service settings: branding paths, available maps and the default map, currency, locale, demo credentials, registration and mobile app behavior, colour themes, legal texts, and the defaults applied to newly created users. Takes no parameters beyond the session credential.", "operationId": "dealerSettingsServiceRead", "responses": { "200": { "description": "Service settings", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "value": { "$ref": "#/components/schemas/ServiceSettings" } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/dealer/settings/service/update": { "post": { "tags": [ "Dealer" ], "summary": "Update service settings", "description": "Update the current dealer's service settings. Branding images, that is wallpapers, logos, and favicons, cannot be changed here: use the branding image upload and delete operations instead.\n\n**This is a full replacement, not a partial update, and it covers more fields than are listed below.** Any writable setting you omit is reset to its default, including settings this schema does not enumerate. Sending only the fields documented here was observed to silently clear `email_special` and flip `no_auto_create_rules` from `true` to `false`.\n\nAlways call the service settings read operation first, modify the fields you intend to change, and send everything back. Do not construct a request from this schema alone.", "operationId": "dealerSettingsServiceUpdate", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServiceSettingsUpdate" } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "409": { "description": "Entity already exists, error code 247: the domain is already used by another dealer", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/timezone/list": { "post": { "tags": [ "Timezone" ], "summary": "List timezones", "operationId": "timezoneList", "description": "List every time zone the platform supports, with localized descriptions.\n\nThis operation requires no authentication and no permissions.\n\nOnly zones under the `Africa`, `America`, `Asia`, `Atlantic`, `Australia`, `Europe`, `Indian`, and `Pacific` prefixes are returned, and only those for which a country code can be resolved. Verified live: 405 zones on the European platform.", "security": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "locale" ], "properties": { "locale": { "type": "string", "description": "Locale used for the `description` of each zone.", "example": "en" } } } } } }, "responses": { "200": { "description": "Supported time zones", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "list": { "type": "array", "description": "Supported time zones, ordered by `zone_id`.", "readOnly": true, "items": { "$ref": "#/components/schemas/TimeZone" } } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/order/read": { "post": { "tags": [ "Order" ], "summary": "Read order", "operationId": "orderRead", "description": "Read a single equipment order belonging to the current dealer.\n\nAn order that exists but belongs to another dealer returns error code 201, the same as one that does not exist, so a caller cannot use this operation to probe for other dealers' order IDs.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "order_id" ], "properties": { "order_id": { "type": "integer", "description": "Order ID.", "minimum": 1, "example": 12341 } } } } } }, "responses": { "200": { "description": "The order", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "value": { "$ref": "#/components/schemas/Order" } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/gateways/email/list": { "post": { "tags": [ "Gateways" ], "summary": "List email gateways", "operationId": "gatewaysEmailList", "description": "List the email gateways available to the current dealer, and report which one is currently bound.\n\nThe response separates gateways the dealer owns from gateways that can be leased from the platform owner. Takes no parameters beyond the session credential.\n\nA dealer that *is* the platform owner receives an empty `leasable` list, since there is nobody to lease from.", "responses": { "200": { "description": "Email gateways", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "bound_gateway": { "type": [ "integer", "null" ], "description": "ID of the gateway currently bound to this dealer, or `null` when none is bound.", "readOnly": true, "example": 2 }, "own": { "type": "array", "description": "Gateways owned by this dealer.", "readOnly": true, "items": { "$ref": "#/components/schemas/DealerOwnEmailGateway" } }, "leasable": { "type": "array", "description": "Gateways offered for lease by the platform owner.", "readOnly": true, "items": { "$ref": "#/components/schemas/LeasableEmailGateway" } } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/subpaas/list": { "post": { "tags": [ "Subpaas" ], "summary": "List sub-dealers", "operationId": "subpaasList", "description": "List the sub-dealers belonging to the current dealer, with per-sub-dealer user and device counts, plus optional text filtering, ordering and pagination.\n\nEvery parameter is optional.", "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object", "properties": { "filter": { "type": "string", "description": "Text filter." }, "order_by": { "type": "string", "description": "Field to order by.", "enum": [ "subpaas_id", "title", "jur_name", "login", "block_type", "creation_date" ], "default": "subpaas_id" }, "ascending": { "type": "boolean", "description": "Order direction. Ascending when `true`.", "default": true }, "offset": { "type": "integer", "description": "Starting offset, for pagination.", "minimum": 0, "default": 0 }, "limit": { "type": "integer", "description": "Maximum number of records to return.", "minimum": 0 } } } } } }, "responses": { "200": { "description": "Sub-dealers", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "list": { "type": "array", "readOnly": true, "description": "The matching sub-dealers.", "items": { "$ref": "#/components/schemas/SubpaasListEntry" } }, "count": { "type": "integer", "readOnly": true, "description": "Total number of matching records, ignoring `offset` and `limit`.", "example": 1 } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission, or the dealer is not eligible to have sub-dealers.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/subpaas/read": { "post": { "tags": [ "Subpaas" ], "summary": "Read sub-dealer", "operationId": "subpaasRead", "description": "Read a single sub-dealer belonging to the current dealer.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "subpaas_id" ], "properties": { "subpaas_id": { "type": "integer", "description": "Sub-dealer ID.", "example": 97834 } } } } } }, "responses": { "200": { "description": "The sub-dealer", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "value": { "$ref": "#/components/schemas/Subpaas" } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission, or the dealer is not eligible to have sub-dealers.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/subpaas/create": { "post": { "tags": [ "Subpaas" ], "summary": "Create sub-dealer", "operationId": "subpaasCreate", "description": "Create a sub-dealer under the current dealer.\n\n**This operation sends email.** On success the platform notifies both the parent dealer and the platform managers.\n\nThe current dealer must be of the PaaS contract type, must not be blocked, and its plan must permit sub-dealer accounts. Failing any of those returns error code 13.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "password", "title", "jur_name", "email", "jur_country", "link_monitoring" ], "properties": { "password": { "type": "string", "format": "password", "description": "Sub-dealer's password. Must satisfy the platform password policy." }, "title": { "type": "string", "description": "Sub-dealer display name.", "minLength": 1, "maxLength": 50, "example": "Rus Sub-PaaS" }, "jur_name": { "type": "string", "description": "Legal company name.", "maxLength": 100, "example": "OOO Sub-PaaS" }, "email": { "type": "string", "description": "Company email address.", "format": "email", "example": "sub-dealer@email.com" }, "jur_country": { "type": "string", "description": "Sub-dealer's country.", "maxLength": 255, "example": "country" }, "link_monitoring": { "type": "string", "description": "Sub-dealer's monitoring domain. Must be a valid internationalized domain name and must not be empty.", "maxLength": 255, "example": "sub.navixy.com" }, "contact_fio": { "type": "string", "description": "Optional. Contact person.", "maxLength": 100, "example": "fio" }, "contact_post": { "type": "string", "description": "Optional. Contact person position.", "maxLength": 50, "example": "post" }, "contact_phone": { "type": "string", "description": "Optional. Contact person's phone.", "maxLength": 255, "example": "phone" } } } } } }, "responses": { "200": { "description": "Sub-dealer created", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "id": { "type": "integer", "description": "ID of the created sub-dealer.", "readOnly": true, "example": 18 } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission, or the dealer is not eligible to have sub-dealers.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/subpaas/update": { "post": { "tags": [ "Subpaas" ], "summary": "Update sub-dealer", "operationId": "subpaasUpdate", "description": "Update an existing sub-dealer.\n\nUnlike create, this operation requires `subpaas_id` and `block_type`, and does not accept `password`. Use the password change operation for that.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "subpaas_id", "block_type", "title", "jur_name", "email", "jur_country", "link_monitoring" ], "properties": { "subpaas_id": { "type": "integer", "description": "ID of the sub-dealer to update.", "example": 97834 }, "block_type": { "type": "string", "description": "Block status of the sub-dealer panel and its users.", "enum": [ "NOT_BLOCKED", "INITIAL_BLOCK", "BLOCK_LOGIN", "CLIENTS_BLOCKED" ], "example": "NOT_BLOCKED" }, "title": { "type": "string", "description": "Sub-dealer display name.", "minLength": 1, "maxLength": 50, "example": "Rus Sub-PaaS" }, "jur_name": { "type": "string", "description": "Legal company name.", "maxLength": 100, "example": "OOO Sub-PaaS" }, "email": { "type": "string", "description": "Company email address.", "format": "email", "example": "sub-dealer@email.com" }, "jur_country": { "type": "string", "description": "Sub-dealer's country.", "maxLength": 255, "example": "country" }, "link_monitoring": { "type": "string", "description": "Sub-dealer's monitoring domain. Must be a valid internationalized domain name and must not be empty.", "maxLength": 255, "example": "sub.navixy.com" }, "contact_fio": { "type": "string", "description": "Optional. Contact person.", "maxLength": 100, "example": "fio" }, "contact_post": { "type": "string", "description": "Optional. Contact person position.", "maxLength": 50, "example": "post" }, "contact_phone": { "type": "string", "description": "Optional. Contact person's phone.", "maxLength": 255, "example": "phone" } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission, or the dealer is not eligible to have sub-dealers.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/subpaas/password/change": { "post": { "tags": [ "Subpaas" ], "summary": "Change sub-dealer password", "operationId": "subpaasPasswordChange", "description": "Set a new password for a sub-dealer.\n\nThe current password is **not** required: a parent dealer can reset a sub-dealer's password directly. The new password must satisfy the platform password policy and must not match a recently used one.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "subpaas_id", "new_password" ], "properties": { "subpaas_id": { "type": "integer", "description": "Sub-dealer ID.", "example": 97834 }, "new_password": { "type": "string", "format": "password", "description": "New password. Trimmed before validation." } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission, or the dealer is not eligible to have sub-dealers.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/subpaas/session/create": { "post": { "tags": [ "Subpaas" ], "summary": "Create sub-dealer session", "operationId": "subpaasSessionCreate", "description": "Open a panel session as one of your sub-dealers and return its session hash.\n\nUse the returned hash exactly as one returned by the authenticate operation. It grants access to that sub-dealer's panel, so treat it as a credential.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "subpaas_id" ], "properties": { "subpaas_id": { "type": "integer", "description": "Sub-dealer ID.", "example": 97834 } } } } } }, "responses": { "200": { "description": "Session opened as the sub-dealer", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "hash": { "type": "string", "description": "Session key for the sub-dealer's panel. Pass it in the `Authorization` header as `NVX `.", "readOnly": true, "example": "fa7bf873fab9333144e171372a321b06" } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission, or the dealer is not eligible to have sub-dealers.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tariff/list": { "post": { "tags": [ "Tariff" ], "summary": "List plans", "operationId": "tariffList", "description": "List the plans belonging to the current dealer, with optional filtering by device type, text filtering, ordering and pagination.\n\nThe response also carries `wholesale_service_prices`, the prices the dealer itself is charged, which is not part of any individual plan.", "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object", "properties": { "device_type": { "type": "string", "description": "Optional. Filter by device type.", "enum": [ "tracker", "camera", "socket" ] }, "filter": { "type": "string", "description": "Optional. Text filter." }, "order_by": { "type": "string", "description": "Optional. Field to order by.", "enum": [ "id", "name", "device_type", "group_id", "price" ], "default": "id" }, "ascending": { "type": "boolean", "description": "Optional. Ascending when `true`.", "default": true }, "offset": { "type": "integer", "description": "Optional. Starting offset, for pagination.", "minimum": 0, "default": 0 }, "limit": { "type": "integer", "description": "Optional. Maximum records to return.", "minimum": 0 } } } } } }, "responses": { "200": { "description": "Plans", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "list": { "type": "array", "readOnly": true, "description": "The matching plans.", "items": { "$ref": "#/components/schemas/Plan" } }, "wholesale_service_prices": { "allOf": [ { "$ref": "#/components/schemas/ServicePrices" } ], "readOnly": true, "description": "Per-unit service prices charged to the dealer, as opposed to the prices in each plan." }, "count": { "type": "integer", "readOnly": true, "description": "Total number of matching records, ignoring `offset` and `limit`.", "example": 1 } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tariff/read": { "post": { "tags": [ "Tariff" ], "summary": "Read plan", "operationId": "tariffRead", "description": "Read a single plan belonging to the current dealer.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "tariff_id" ], "properties": { "tariff_id": { "type": "integer", "description": "Plan ID.", "minimum": 1, "example": 12163 } } } } } }, "responses": { "200": { "description": "The plan", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "value": { "$ref": "#/components/schemas/Plan" } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tariff/create": { "post": { "tags": [ "Tariff" ], "summary": "Create plan", "operationId": "tariffCreate", "description": "Create a plan for the current dealer.\n\nThe plan definition is passed as a `tariff` object with no `id`, since the platform assigns one. Plan creation counts against the dealer's plan quota.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "tariff" ], "properties": { "tariff": { "$ref": "#/components/schemas/PlanDraft" } } } } } }, "responses": { "200": { "description": "Plan created", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "id": { "type": "integer", "description": "ID of the created plan.", "readOnly": true, "example": 12163 } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tariff/update": { "post": { "tags": [ "Tariff" ], "summary": "Update plan", "operationId": "tariffUpdate", "description": "Update an existing plan.\n\nThe plan definition is passed as a `tariff` object that includes `id` but omits `device_type`: a plan's device type cannot be changed after creation.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "tariff" ], "properties": { "tariff": { "$ref": "#/components/schemas/PlanEdit" } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tariff/defaults/read": { "post": { "tags": [ "Tariff" ], "summary": "Read plan defaults", "operationId": "tariffDefaultsRead", "description": "Read the plan defaults applied when a device is registered: which plan it lands on, and what bonus and free period it receives.\n\nDefaults are keyed by device type. Only `tracker` was observed in responses. Takes no parameters beyond the session credential.\n\nNote that the defaults sit at the top level of the response, not nested under a `value` key.", "responses": { "200": { "description": "Plan defaults, keyed by device type", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "tracker": { "$ref": "#/components/schemas/TariffDefaults" } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tariff/defaults/update": { "post": { "tags": [ "Tariff" ], "summary": "Update plan defaults", "operationId": "tariffDefaultsUpdate", "description": "Update the plan defaults for a device type.\n\nThe defaults object sits at the top level of the request under its device-type key, not nested under a wrapper.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "tracker" ], "properties": { "tracker": { "$ref": "#/components/schemas/TariffDefaults" } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/list": { "post": { "tags": [ "User" ], "summary": "List users", "operationId": "userList", "description": "List the end users of the dealer, with optional text filtering, ordering and pagination.", "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object", "properties": { "filter": { "type": "string", "description": "Optional. Text filter." }, "order_by": { "type": "string", "description": "Optional. Field to order by." }, "ascending": { "type": "boolean", "description": "Optional. Ascending when `true`.", "default": true }, "offset": { "type": "integer", "description": "Optional. Starting offset, for pagination.", "minimum": 0, "default": 0 }, "limit": { "type": "integer", "description": "Optional. Maximum records to return.", "minimum": 0 } } } } } }, "responses": { "200": { "description": "Users", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "list": { "type": "array", "readOnly": true, "items": { "$ref": "#/components/schemas/User" } }, "count": { "type": "integer", "readOnly": true, "description": "Total matching records, ignoring `offset` and `limit`." } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/read": { "post": { "tags": [ "User" ], "summary": "Read user", "operationId": "userRead", "description": "Read a single end user.\n\nThe response carries five sibling keys rather than a single `value`: the user profile, any discount, the default plan ID of the dealer, the block parameters of the user, and the dealer-level MFA settings.\n\nA sub-user, or a user belonging to another dealer, returns error code 201 exactly as a missing one does.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "user_id" ], "properties": { "user_id": { "type": "integer", "description": "ID of the user. Must belong to the current dealer and must not be a sub-user.", "minimum": 1, "example": 231485 } } } } } }, "responses": { "200": { "description": "The user, with related settings", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "value": { "$ref": "#/components/schemas/User" }, "discount": { "anyOf": [ { "$ref": "#/components/schemas/UserDiscount" }, { "type": "null" } ], "description": "Discount applied to this user, or `null` when none." }, "default_tariff_id": { "type": [ "integer", "null" ], "description": "ID of the default plan of the dealer." }, "block_parameters": { "type": [ "object", "null" ], "description": "Parameters governing how and when the user is blocked.", "additionalProperties": true }, "dealer_mfa_settings": { "type": [ "object", "null" ], "description": "Dealer-level multi-factor authentication settings that apply to this user.", "additionalProperties": true } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/export": { "post": { "tags": [ "User" ], "summary": "Export users", "operationId": "userExport", "description": "Export the user list as a spreadsheet. Unlike every other operation here, a successful response is a file download rather than a JSON body.", "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object", "properties": { "format": { "type": "string", "description": "Output file format.", "enum": [ "csv", "xlsx" ], "default": "xlsx" }, "columns": { "type": "array", "description": "Columns to include, in order. Must not be empty.", "minItems": 1, "items": { "type": "string" }, "default": [ "id", "login", "first_name", "middle_name", "last_name", "phone" ] }, "filter": { "type": "string", "description": "Optional. Text filter, as for the list operation." } } } } } }, "responses": { "200": { "description": "The exported file.", "content": { "text/csv": { "schema": { "type": "string" } }, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/change_password": { "post": { "tags": [ "User" ], "summary": "Change user password", "operationId": "userChangePassword", "description": "Set a new password for an end user.\n\nNote the parameter is `password`, not `new_password` as the dealer and subpaas equivalents use, and no current password is required: a dealer sets a user password without knowing the old one.\n\nThe value must satisfy the password policy of the dealer, returned as `password_policy` by the dealer get info operation.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "user_id", "password" ], "properties": { "user_id": { "type": "integer", "description": "ID of the user. Must belong to the current dealer and must not be a sub-user.", "minimum": 1, "example": 231485 }, "password": { "type": "string", "format": "password", "description": "New password. Must satisfy the password policy of the dealer and must not match a recently used password." } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/corrupt": { "post": { "tags": [ "User" ], "summary": "Corrupt user", "operationId": "userCorrupt", "description": "Corrupt an end user, marking the account and its data as unusable.\n\n**The login of the user must be supplied alongside `user_id`**, which acts as a deliberate confirmation step for a destructive operation.\n\nBy default the tracker clones of the user are corrupted too.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "user_id", "login" ], "properties": { "user_id": { "type": "integer", "description": "ID of the user. Must belong to the current dealer and must not be a sub-user.", "minimum": 1, "example": 231485 }, "login": { "type": "string", "description": "Login of the user being corrupted.", "minLength": 1, "example": "user@example.com" }, "corrupt_clones": { "type": "boolean", "description": "Whether to corrupt the tracker clones of the user as well.", "default": true } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/session/create": { "post": { "tags": [ "User" ], "summary": "Create user session", "operationId": "userSessionCreate", "description": "Create a session for an end user and return its hash, letting a dealer act on behalf of that user in the user-facing API without knowing their password.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "user_id" ], "properties": { "user_id": { "type": "integer", "description": "ID of the user. Must belong to the current dealer and must not be a sub-user.", "minimum": 1, "example": 231485 } } } } } }, "responses": { "200": { "description": "The session of the user", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "hash": { "type": "string", "description": "Session key for the end user. Use it against the user-facing API, not the Admin Panel API.", "readOnly": true, "example": "fa7bf873fab9333144e171372a321b06" } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/transaction/list": { "post": { "tags": [ "User" ], "summary": "List user transactions", "operationId": "userTransactionList", "description": "List balance transactions for an end user over a time interval.\n\n`from` and `to` are **top-level parameters**, not nested under an `interval` object. Both are mandatory.\n\nThe interval is bounded: too wide a span fails with error code 211 rather than truncating.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "user_id", "from", "to" ], "properties": { "user_id": { "type": "integer", "description": "ID of the user. Must belong to the current dealer and must not be a sub-user.", "minimum": 1, "example": 231485 }, "from": { "type": "string", "description": "Start of the interval, as `YYYY-MM-DD HH:MM:SS`.", "example": "2026-07-01 00:00:00" }, "to": { "type": "string", "description": "End of the interval, as `YYYY-MM-DD HH:MM:SS`.", "example": "2026-08-01 00:00:00" }, "limit": { "type": "integer", "description": "Optional. Maximum records to return.", "minimum": 1, "maximum": 20000 } } } } } }, "responses": { "200": { "description": "The transactions of the user", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "list": { "type": "array", "readOnly": true, "items": { "$ref": "#/components/schemas/UserTransaction" } } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/transaction/change_balance": { "post": { "tags": [ "User" ], "summary": "Change user balance", "operationId": "userTransactionChangeBalance", "description": "Adjust the balance or bonus balance of an end user by a signed amount, recording a transaction.\n\nA descriptive `text` of at least 5 characters is mandatory, so every adjustment carries a reason.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "user_id", "amount", "type", "text" ], "properties": { "user_id": { "type": "integer", "description": "ID of the user. Must belong to the current dealer and must not be a sub-user.", "minimum": 1, "example": 231485 }, "amount": { "type": "number", "description": "Signed amount to apply. Negative values debit the balance.", "minimum": -9999999999.9999, "maximum": 9999999999.9999, "example": 10.5 }, "type": { "type": "string", "description": "Which balance to adjust.", "example": "main" }, "text": { "type": "string", "description": "Reason for the adjustment, recorded on the transaction.", "minLength": 5, "maxLength": 200, "example": "Manual top-up after support request" } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/create": { "post": { "tags": [ "User" ], "summary": "Create user", "operationId": "userCreate", "description": "Create an end user.\n\nThe profile is passed as a `user` object whose shape depends on `legal_type`. Alongside it, `password`, `locale`, and `time_zone` are all mandatory and sit at the top level rather than inside `user`.\n\nA login already in use fails with error code 206.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "user", "password", "locale", "time_zone" ], "properties": { "user": { "$ref": "#/components/schemas/UserEditForm" }, "password": { "type": "string", "format": "password", "description": "Initial password. Must satisfy the password policy of the dealer." }, "locale": { "type": "string", "description": "Locale for the new user.", "example": "en_US" }, "time_zone": { "type": "string", "description": "Time zone ID for the new user. See the timezone list operation.", "example": "Europe/London" }, "discount": { "anyOf": [ { "$ref": "#/components/schemas/UserDiscount" }, { "type": "null" } ], "description": "Optional discount to apply to this user." }, "default_tariff_id": { "type": [ "integer", "null" ], "description": "Optional. Plan the user is placed on. Must exist and belong to the dealer." }, "comment": { "type": "string", "description": "Optional free-text comment.", "maxLength": 255 } } } } } }, "responses": { "200": { "description": "User created", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "readOnly": true, "example": true }, "id": { "type": "integer", "description": "ID of the created user.", "readOnly": true, "example": 231485 } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/update": { "post": { "tags": [ "User" ], "summary": "Update user", "operationId": "userUpdate", "description": "Update an end user.\n\nThe `user` object must carry both `id` and `activated`; omitting either fails with an `errors` entry naming `user.id` or `user.activated`. Changing `login` to one already in use fails with error code 206.\n\nAs with create, the shape of `user` depends on `legal_type`.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "user" ], "properties": { "user": { "allOf": [ { "$ref": "#/components/schemas/UserEditForm" } ], "description": "The user to update. Must include `id` and `activated` in addition to the fields required by its `legal_type`." }, "discount": { "anyOf": [ { "$ref": "#/components/schemas/UserDiscount" }, { "type": "null" } ], "description": "Optional discount to apply to this user." }, "default_tariff_id": { "type": [ "integer", "null" ], "description": "Optional. Plan the user is placed on. Must exist and belong to the dealer." }, "comment": { "type": "string", "description": "Optional free-text comment.", "maxLength": 255 } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/upload": { "post": { "tags": [ "User" ], "summary": "Upload users", "operationId": "userUpload", "description": "Create users in bulk from a CSV or XLS spreadsheet.\n\nRequires a `multipart/form-data` request with the spreadsheet as a part named `file`, in the same way as the branding image upload. **At most 10000 rows** are processed.\n\nColumn headers are localized, so a Russian-locale file uses Russian headers. Columns may appear in any order. `Legal status` is a number: `1` individual, `2` legal entity, `3` sole trader. Legal entities and sole traders require the address and registration columns as well as the always-required ones, except that a sole trader does not require `Legal name`.\n\nNew users take the time zone from the `default_user_time_zone` service setting.", "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "type": "object", "required": [ "file" ], "properties": { "file": { "type": "string", "format": "binary", "description": "CSV or XLS spreadsheet. CSV uses `;` as the column separator." }, "redirect_target": { "type": "string", "format": "uri", "description": "Optional URL to redirect to instead of returning the JSON response body, as for the branding image upload." } } } } } }, "responses": { "200": { "description": "Upload processed", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "readOnly": true, "example": true }, "total": { "type": "integer", "description": "Number of rows processed.", "readOnly": true, "example": 1 }, "errors": { "type": "integer", "description": "Number of rows that failed.", "readOnly": true, "example": 0 } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/menu/preset/list": { "post": { "tags": [ "User" ], "summary": "List menu presets", "operationId": "userMenuPresetList", "description": "List the menu presets available to the dealer, each with its owner and current assignments.\n\nPresets owned by `platform` are supplied by Navixy. Takes no parameters beyond the session credential.", "responses": { "200": { "description": "Menu presets", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "list": { "type": "array", "readOnly": true, "items": { "$ref": "#/components/schemas/MenuPresetListEntry" } } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/menu/preset/create": { "post": { "tags": [ "User" ], "summary": "Create menu preset", "operationId": "userMenuPresetCreate", "description": "Create a menu preset for the dealer. The layout is passed as a `preset` object with no `id`.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "preset" ], "properties": { "preset": { "$ref": "#/components/schemas/MenuPresetDraft" } } } } } }, "responses": { "200": { "description": "Preset created", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "id": { "type": "integer", "description": "ID of the created preset.", "readOnly": true, "example": 346 } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/menu/preset/update": { "post": { "tags": [ "User" ], "summary": "Update menu preset", "operationId": "userMenuPresetUpdate", "description": "Update a menu preset. The `preset` object must carry its `id`. Presets owned by `platform` cannot be updated.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "preset" ], "properties": { "preset": { "$ref": "#/components/schemas/MenuPresetEdit" } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/menu/preset/delete": { "post": { "tags": [ "User" ], "summary": "Delete menu preset", "operationId": "userMenuPresetDelete", "description": "Delete a menu preset. Users assigned to it fall back to the dealer default.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "preset_id" ], "properties": { "preset_id": { "type": "integer", "description": "Menu preset ID.", "minimum": 1, "example": 346 } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/menu/preset/assign": { "post": { "tags": [ "User" ], "summary": "Assign menu preset", "operationId": "userMenuPresetAssign", "description": "Assign a menu preset, either as the dealer default or to an explicit list of users.\n\nThe `target` object is a discriminated union on `type`: `default` makes the preset the fallback for users with no explicit assignment, and `users` assigns it to up to 10000 named user IDs.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "preset_id", "target" ], "properties": { "preset_id": { "type": "integer", "description": "Menu preset ID.", "minimum": 1, "example": 346 }, "target": { "$ref": "#/components/schemas/MenuPresetAssignmentTarget" } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/menu/item/list": { "post": { "tags": [ "User" ], "summary": "List menu items", "operationId": "userMenuItemList", "description": "List every menu item available for use when composing a preset.\n\nNote the path: this operation is at `panel/user/menu/item/list`, not under `menu/preset/`. Takes no parameters beyond the session credential.", "responses": { "200": { "description": "Available menu items", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "list": { "type": "array", "readOnly": true, "items": { "$ref": "#/components/schemas/MenuItemDestination" } } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/mfa/settings/update": { "post": { "tags": [ "User" ], "summary": "Update MFA settings", "operationId": "userMfaSettingsUpdate", "description": "Set the multi-factor authentication policy for specific users, or for all of them.\n\nBoth `target` and `settings` are discriminated unions on `type`. Note the target list is capped at **100** user IDs, unlike the menu preset assignment which allows 10000.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "target", "settings" ], "properties": { "target": { "$ref": "#/components/schemas/MfaTarget" }, "settings": { "$ref": "#/components/schemas/MfaSettings" } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/mfa/settings/default/read": { "post": { "tags": [ "User" ], "summary": "Read default MFA settings", "operationId": "userMfaSettingsDefaultRead", "description": "Read the dealer-level default multi-factor authentication policy, applied to users with no explicit setting.\n\n`value` is `null` when no default has been configured. Takes no parameters beyond the session credential.", "responses": { "200": { "description": "The default policy", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "value": { "anyOf": [ { "$ref": "#/components/schemas/MfaSettings" }, { "type": "null" } ], "description": "The configured default, or `null` when none is set." } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/user/mfa/settings/default/update": { "post": { "tags": [ "User" ], "summary": "Update default MFA settings", "operationId": "userMfaSettingsDefaultUpdate", "description": "Set the dealer-level default multi-factor authentication policy. It applies to users with no explicit setting of their own.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "settings" ], "properties": { "settings": { "$ref": "#/components/schemas/MfaSettings" } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/list": { "post": { "tags": [ "Tracker" ], "summary": "List trackers", "operationId": "trackerList", "description": "List the dealer's trackers, with optional filtering by owner, plan, and clone status.", "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object", "properties": { "user_id": { "type": "integer", "description": "Optional. Filter to one owner.", "minimum": 1 }, "tariff_id": { "type": "integer", "description": "Optional. Filter to one plan.", "minimum": 1 }, "clones_filter": { "type": "string", "description": "Optional. Whether to include clones." }, "filter": { "type": "string", "description": "Optional. Text filter." }, "order_by": { "type": "string", "description": "Optional. Field to order by." }, "ascending": { "type": "boolean", "default": true }, "offset": { "type": "integer", "minimum": 0, "default": 0 }, "limit": { "type": "integer", "minimum": 0 } } } } } }, "responses": { "200": { "description": "Trackers", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "list": { "type": "array", "readOnly": true, "items": { "$ref": "#/components/schemas/Tracker" } }, "count": { "type": "integer", "readOnly": true, "description": "Total matching records, ignoring `offset` and `limit`." } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/read": { "post": { "tags": [ "Tracker" ], "summary": "Read tracker", "operationId": "trackerRead", "description": "Read a single tracker.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "tracker_id" ], "properties": { "tracker_id": { "type": "integer", "description": "Tracker ID. Must belong to the current dealer.", "minimum": 1, "example": 134537 } } } } } }, "responses": { "200": { "description": "The tracker", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "value": { "$ref": "#/components/schemas/Tracker" } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/clone": { "post": { "tags": [ "Tracker" ], "summary": "Clone tracker", "operationId": "trackerClone", "description": "Create a clone of a tracker for another user. A clone shares the source device but appears as a separate tracker to its owner.\n\nThe source tracker must not itself be a clone.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "tracker_id", "user_id", "label" ], "properties": { "tracker_id": { "type": "integer", "description": "Tracker ID. Must belong to the current dealer.", "minimum": 1, "example": 134537 }, "user_id": { "type": "integer", "description": "ID of the user who will own the clone. Must not be the owner of the source tracker.", "minimum": 1, "example": 354468 }, "label": { "type": "string", "description": "Label for the clone.", "minLength": 1, "example": "Courier" } } } } } }, "responses": { "200": { "description": "Clone created", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "id": { "type": "integer", "description": "ID of the created clone.", "readOnly": true } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/batch_clone": { "post": { "tags": [ "Tracker" ], "summary": "Batch clone trackers", "operationId": "trackerBatchClone", "description": "Clone many trackers to one user in a single call. At most **1000** trackers per request.\n\nNote the differing limit: `batch_delete_clones` accepts only 500.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "user_id", "tracker_ids" ], "properties": { "user_id": { "type": "integer", "description": "ID of the user who will own the clones.", "minimum": 1, "example": 998836 }, "tracker_ids": { "type": "array", "description": "Trackers to clone. Between 1 and 1000 inclusive.", "minItems": 1, "maxItems": 1000, "items": { "type": "integer", "minimum": 1 }, "example": [ 134537, 458412 ] }, "ignore_existing": { "type": "boolean", "description": "When `true`, trackers the user already has a clone of are skipped instead of failing.", "example": true } } } } } }, "responses": { "200": { "description": "Clones created", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "list": { "type": "array", "readOnly": true, "description": "Per-tracker outcome.", "items": { "type": "object", "additionalProperties": true } } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/delete_clone": { "post": { "tags": [ "Tracker" ], "summary": "Delete tracker clone", "operationId": "trackerDeleteClone", "description": "Delete a clone. The specified tracker must itself be a clone; deleting a source tracker this way fails with error code 249.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "tracker_id" ], "properties": { "tracker_id": { "type": "integer", "description": "Tracker ID. Must belong to the current dealer.", "minimum": 1, "example": 134537 } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/batch_delete_clones": { "post": { "tags": [ "Tracker" ], "summary": "Batch delete tracker clones", "operationId": "trackerBatchDeleteClones", "description": "Delete many clones in one call. At most **500** trackers per request, and the list must not be empty or contain nulls.\n\nNote the differing limit: `batch_clone` accepts 1000. The Navixy interface exposes a lower limit again, selecting at most 20 at a time.\n\nThe response reports counts and, when some could not be deleted, why.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "trackers" ], "properties": { "trackers": { "type": "array", "description": "Clone IDs to delete. Up to 500, no nulls, must not be empty.", "minItems": 1, "maxItems": 500, "items": { "type": "integer", "minimum": 1 }, "example": [ 134537, 458412 ] } } } } } }, "responses": { "200": { "description": "Deletion result", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "deleted_count": { "type": "integer", "readOnly": true, "description": "How many clones were deleted." }, "not_deleted_count": { "type": "integer", "readOnly": true, "description": "How many could not be deleted." }, "not_deleted_trackers": { "type": "array", "readOnly": true, "description": "Per-tracker failure detail. Omitted when empty.", "items": { "type": "object", "properties": { "id": { "type": "integer" }, "error": { "type": "string" } } } } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/corrupt": { "post": { "tags": [ "Tracker" ], "summary": "Corrupt tracker", "operationId": "trackerCorrupt", "description": "Corrupt a tracker, marking its source device unusable. **There is no undo.**\n\nBy default the clones of the tracker are corrupted too. Leaving `corrupt_clones` as `false` while clones exist fails with error code 253.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "tracker_id" ], "properties": { "tracker_id": { "type": "integer", "description": "Tracker ID. Must belong to the current dealer.", "minimum": 1, "example": 134537 }, "corrupt_clones": { "type": "boolean", "description": "Whether to corrupt the clones of this tracker as well.", "default": true } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/move": { "post": { "tags": [ "Tracker" ], "summary": "Move tracker", "operationId": "trackerMove", "description": "Reassign a tracker to a different user of the same dealer. The tracker must not be a clone.\n\nThe response returns the **new** tracker ID. Changing the owner creates a new tracker record, so the ID sent in the request no longer refers to the moved tracker afterwards.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "tracker_id", "user_id" ], "properties": { "tracker_id": { "type": "integer", "description": "Tracker ID. Must belong to the current dealer.", "minimum": 1, "example": 134537 }, "user_id": { "type": "integer", "description": "ID of the destination user. Must differ from the current owner and belong to the same dealer.", "minimum": 1, "example": 214034 } } } } } }, "responses": { "200": { "description": "Tracker moved", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "id": { "type": "integer", "description": "ID of the tracker after the move. Moving a tracker to another user creates a **new** tracker ID, so this differs from the `tracker_id` sent in the request. Use this value for subsequent calls about the moved tracker.", "readOnly": true, "example": 1245678 } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/register_retry": { "post": { "tags": [ "Tracker" ], "summary": "Retry tracker registration", "operationId": "trackerRegisterRetry", "description": "Retry registration of a device that failed to register.\n\nRate limited: a second attempt within 120 seconds fails with error code 264. Devices without a GSM module return error code 214.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "tracker_id" ], "properties": { "tracker_id": { "type": "integer", "description": "Tracker ID. Must belong to the current dealer.", "minimum": 1, "example": 134537 }, "send_register_commands": { "type": "boolean", "description": "Whether to send configuration commands to the device as part of the retry.", "example": true } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/settings/update": { "post": { "tags": [ "Tracker" ], "summary": "Update tracker settings", "operationId": "trackerSettingsUpdate", "description": "Update the dealer-editable settings of a tracker.\n\nThe settings sit at the **top level** of the request alongside `tracker_id`, not nested under a wrapper.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "tracker_id" ], "properties": { "tracker_id": { "type": "integer", "description": "Tracker ID. Must belong to the current dealer.", "minimum": 1, "example": 134537 }, "label": { "type": "string", "description": "Tracker label.", "example": "Courier" }, "deleted": { "type": "boolean", "description": "Whether the tracker is marked deleted.", "example": false } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/source/update": { "post": { "tags": [ "Tracker" ], "summary": "Update tracker source", "operationId": "trackerSourceUpdate", "description": "Update the source device behind a tracker, for example to block or unblock it.\n\nHolding `trackers: update` may not be sufficient: a session with the full `trackers` permission set was observed to receive `403` code 13 from this operation while every other `trackers: update` operation succeeded. Something beyond the declared permission gates it.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "tracker_id" ], "properties": { "tracker_id": { "type": "integer", "description": "Tracker ID. Must belong to the current dealer.", "minimum": 1, "example": 134537 }, "blocked": { "type": "boolean", "description": "Whether the source device is blocked.", "example": false } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/tariff/change": { "post": { "tags": [ "Tracker" ], "summary": "Change tracker plan", "operationId": "trackerTariffChange", "description": "Move a tracker to a different plan, optionally charging or repaying immediately.\n\nThis operation has billing consequences: it can create a transaction against the user's balance.\n\nThe new plan must have a device limit at least as large as the tracker count of the owning user, otherwise error code 221 is returned.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "tracker_id", "tariff_id", "repay", "charge" ], "properties": { "tracker_id": { "type": "integer", "description": "Tracker ID. Must belong to the current dealer.", "minimum": 1, "example": 134537 }, "tariff_id": { "type": "integer", "description": "ID of the destination plan.", "minimum": 1, "example": 15843 }, "repay": { "type": "boolean", "description": "Whether to repay the unused remainder of the current plan.", "example": false }, "charge": { "type": "boolean", "description": "Whether to charge for the new plan immediately.", "example": true } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/console/connect": { "post": { "tags": [ "Tracker" ], "summary": "Connect tracker console", "operationId": "trackerConsoleConnect", "description": "Open an AirConsole session against a device, returning a key used to attach to the console stream.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "tracker_id" ], "properties": { "tracker_id": { "type": "integer", "description": "Tracker ID. Must belong to the current dealer.", "minimum": 1, "example": 134537 } } } } } }, "responses": { "200": { "description": "Console session", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "key": { "type": "string", "description": "Session key for the console stream.", "readOnly": true, "example": "6a21fd30edc46487a59957d407cf3c6436082b89" }, "timestamp": { "type": "integer", "description": "Unix timestamp the session was opened.", "readOnly": true, "example": 1785840045 } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/active/history/list": { "post": { "tags": [ "Tracker" ], "summary": "List tracker active history", "operationId": "trackerActiveHistoryList", "description": "Report how many trackers were active in each month of a range, with the trackers counted.\n\n**`from` and `to` are months, formatted `YYYY-MM`**, and both are mandatory. Passing a full date and time fails validation. Note this differs from the user transaction list, which uses the same two parameter names with full `YYYY-MM-DD HH:MM:SS` values.\n\nRequires the `report` operation on `trackers`, which is distinct from `read`.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "from", "to" ], "properties": { "from": { "type": "string", "description": "First month of the range, as `YYYY-MM`.", "pattern": "^\\d{4}-\\d{2}$", "example": "2026-06" }, "to": { "type": "string", "description": "Last month of the range, as `YYYY-MM`.", "pattern": "^\\d{4}-\\d{2}$", "example": "2026-08" } } } } } }, "responses": { "200": { "description": "Active tracker history", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true }, "list": { "type": "array", "readOnly": true, "items": { "$ref": "#/components/schemas/ActiveHistoryMonth" } }, "users_map": { "type": "object", "readOnly": true, "description": "Owners referenced by the entries, keyed by user ID.", "additionalProperties": true } } } } } }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } }, "/panel/tracker/raw_command/send": { "post": { "tags": [ "Tracker" ], "summary": "Send raw command", "operationId": "trackerRawCommandSend", "description": "Send a raw protocol command to a device.\n\n**This operation identifies the device by `device_id`, not `tracker_id`**, unlike every other operation on this resource. `device_id` is the identifier on the `source` object of a tracker. Sending `tracker_id` instead fails validation.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "device_id", "command" ], "properties": { "device_id": { "type": "string", "description": "Device identifier, taken from `source.device_id` on the tracker.", "example": "114038727861" }, "command": { "type": "string", "description": "Raw command text, in whatever form the device protocol expects.", "example": "STATUS#" }, "type": { "type": "string", "description": "Command type." } } } } } }, "responses": { "200": { "$ref": "#/components/responses/OK" }, "400": { "description": "Bad request. The response body carries the API-level error code in `status.code`. Validation failures also include an `errors` array.", "$ref": "#/components/responses/ResponseError" }, "403": { "description": "Operation not permitted, error code 13: the session lacks the required permission.", "$ref": "#/components/responses/ResponseError" }, "default": { "$ref": "#/components/responses/ResponseError" } } } } }, "security": [ { "api_key": [] } ], "components": { "securitySchemes": { "api_key": { "type": "apiKey", "description": "Enter the panel session hash with the \"NVX \" prefix, e.g. \"NVX fa7bf873fab9333144e171372a321b06\". Obtain the hash from the accountAuth operation.", "name": "Authorization", "in": "header" } }, "responses": { "OK": { "description": "Successful response", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "`true` if request finished successfully.", "readOnly": true, "example": true } } } } } }, "ResponseError": { "description": "Error response object", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Always false.", "example": false }, "status": { "type": "object", "description": "Error status. Present only when an error occurred.", "properties": { "code": { "type": "integer", "description": "An error code in this API (not a HTTP code)", "example": 201 }, "description": { "type": "string", "description": "An error description", "example": "Not found in the database" } } }, "errors": { "type": "array", "description": "Per-parameter detail, returned with validation failures such as error code 7.", "items": { "type": "object", "properties": { "parameter": { "type": "string", "description": "Name of the parameter that failed validation.", "example": "order_by" }, "error": { "type": "string", "description": "What was wrong with it.", "example": "Should be one of [code, activated, tariff_id, tariff_name, device_type, money_amount, bonus_amount, free_days]" } } } } } } } } } }, "schemas": { "PanelPermissions": { "type": "object", "description": "Permissions granted to a panel session, grouped by category. Each value lists the actions permitted in that category. Which categories appear depends on the features enabled for the dealer, so a category can be absent rather than empty. Treat an absent category as granting nothing.", "readOnly": true, "properties": { "base": { "type": "array", "description": "Base panel permissions.", "items": { "type": "string" }, "example": [ "get_dealer_info" ] }, "service_settings": { "type": "array", "description": "Permissions on service settings.", "items": { "type": "string" }, "example": [ "read", "update" ] }, "notification_settings": { "type": "array", "description": "Permissions on notification settings.", "items": { "type": "string" }, "example": [ "read", "update" ] }, "trackers": { "type": "array", "description": "Permissions on trackers.", "items": { "type": "string" }, "example": [ "corrupt", "create", "delete", "global", "read", "report", "update" ] }, "users": { "type": "array", "description": "Permissions on end users.", "items": { "type": "string" }, "example": [ "corrupt", "create", "read", "update" ] }, "user_sessions": { "type": "array", "description": "Permissions on end user sessions.", "items": { "type": "string" }, "example": [ "create" ] }, "tariffs": { "type": "array", "description": "Permissions on plans.", "items": { "type": "string" }, "example": [ "create", "read", "update" ] }, "transactions": { "type": "array", "description": "Permissions on billing transactions.", "items": { "type": "string" }, "example": [ "create", "read" ] }, "activation_code": { "type": "array", "description": "Permissions on activation codes.", "items": { "type": "string" }, "example": [ "read", "update" ] }, "password": { "type": "array", "description": "Permissions on the dealer password.", "items": { "type": "string" }, "example": [ "update" ] }, "email_gateways": { "type": "array", "description": "Permissions on email gateways.", "items": { "type": "string" }, "example": [ "create", "delete", "read", "send_email", "update" ] }, "subpaas": { "type": "array", "description": "Permissions on sub-dealers. Present only when sub-dealer functionality is enabled for the dealer.", "items": { "type": "string" }, "example": [ "create", "delete", "read", "update" ] }, "paas_payments": { "type": "array", "description": "Permissions on PaaS payments.", "items": { "type": "string" }, "example": [ "create", "send_email" ] }, "paas_tariff": { "type": "array", "description": "Permissions on the dealer's own PaaS plan.", "items": { "type": "string" }, "example": [ "read" ] } } }, "PasswordPolicy": { "type": "object", "description": "Password complexity rules enforced for this dealer. Applies to the dealer password update operation and to end user passwords.", "readOnly": true, "properties": { "min_length": { "type": "integer", "description": "Minimum number of characters.", "example": 12 }, "max_length": { "type": "integer", "description": "Maximum number of characters.", "example": 20 }, "special_chars": { "type": "string", "description": "The characters that count as special.", "example": "!@#$%^&*-=()<>[]{}+:;.,/\\?|~`'\"" }, "min_special_chars_count": { "type": "integer", "description": "Minimum number of special characters required.", "example": 1 }, "min_digits_count": { "type": "integer", "description": "Minimum number of digits required.", "example": 1 }, "min_uppercase_count": { "type": "integer", "description": "Minimum number of uppercase letters required.", "example": 1 }, "min_lowercase_count": { "type": "integer", "description": "Minimum number of lowercase letters required.", "example": 1 } } }, "BrandingImageType": { "type": "string", "description": "Branding image slot. `app_logo` requires the `branding_mobile` dealer feature; every other slot requires `branding_web`. Requesting a slot whose feature is disabled fails with error code 236.", "enum": [ "logo", "favicon", "login_wallpaper", "desktop_wallpaper", "monitoring_logo", "document_logo", "app_logo" ], "example": "logo" }, "Location": { "type": "object", "description": "A geographic point.", "properties": { "lat": { "type": "number", "description": "Latitude in degrees.", "example": 33 }, "lng": { "type": "number", "description": "Longitude in degrees.", "example": 22 } } }, "ActivationCode": { "type": "object", "description": "An activation code, which lets an end user register a device themselves with a predetermined plan, bonus balance, and free period.", "properties": { "code": { "type": "string", "description": "The code value.", "example": "1201245293" }, "tariff_id": { "type": "integer", "description": "ID of the plan applied on activation.", "example": 12163 }, "tariff_name": { "type": "string", "description": "Name of the plan applied on activation.", "example": "Tracker demo plan" }, "bonus_amount": { "type": "integer", "description": "Bonus amount added to the user's balance when a device is activated with this code.", "example": 0 }, "money_amount": { "type": "integer", "description": "Amount of money added to the user's balance on activation.", "example": 0 }, "free_days": { "type": "integer", "description": "Number of free days granted on activation.", "example": 14 }, "device_type": { "type": "string", "description": "Device type the code applies to.", "example": "tracker" }, "activated": { "type": "boolean", "description": "`true` once the code has been used.", "example": true }, "activation_date": { "type": [ "string", "null" ], "description": "When the code was used, or `null` if it has not been activated.", "example": "2020-11-12 20:00:08" }, "device_id": { "type": "integer", "description": "ID of the device activated with this code. `0` if the code has not been activated.", "example": 464606 } } }, "Dealer": { "type": "object", "description": "A dealer: a reseller or distributor of Navixy platform services, with access to the Admin Panel.", "readOnly": true, "properties": { "id": { "type": "integer", "description": "Dealer ID.", "example": 9000 }, "seller_id": { "type": "integer", "description": "ID of the seller this dealer buys from.", "example": 3 }, "parent_dealer_id": { "type": "integer", "description": "Parent dealer ID.", "example": 5001 }, "contract_type": { "type": "string", "description": "Contract type.", "enum": [ "PARTNER", "AGENT", "PAAS" ], "example": "PAAS" }, "tariff_id": { "type": "integer", "description": "PaaS plan ID.", "example": 5 }, "tariff": { "$ref": "#/components/schemas/PaasTariff" }, "demo_tariff": { "type": "boolean", "description": "`true` for trial PaaS plans.", "example": false }, "tracker_tariff_end_date": { "type": [ "string", "null" ], "description": "End date of the tracker plan.", "format": "date", "example": "2015-12-31" }, "store_period": { "type": "string", "description": "Maximum data store period for users on a `demo_tariff`, as an ISO 8601 duration.", "example": "P6M" }, "demo_ends": { "type": [ "string", "null" ], "description": "Trial period end date, or `null` if not on a trial.", "example": null }, "title": { "type": "string", "description": "Dealer display name.", "example": "Navixy Demo" }, "block_status": { "type": "string", "description": "Block status of the panel and its end users.", "enum": [ "NOT_BLOCKED", "INITIAL_BLOCK", "BLOCK_LOGIN", "CLIENTS_BLOCKED" ], "example": "NOT_BLOCKED" }, "legal_name": { "type": "string", "description": "Dealer legal name.", "example": "Company" }, "active_amount": { "type": "integer", "description": "Total number of active trackers, including those of sub-dealers.", "example": 99 }, "active_amount_own": { "type": "integer", "description": "Number of active trackers, excluding those of sub-dealers.", "example": 80 }, "active_amount_subpaas": { "type": "integer", "description": "Number of active trackers belonging to sub-dealers.", "example": 19 }, "active_limit": { "type": "integer", "description": "Maximum number of active trackers allowed.", "example": 100 }, "locale": { "type": "string", "description": "Dealer's default locale.", "example": "en_US" }, "domain": { "type": "string", "description": "Dealer's domain.", "example": "demo.navixy.com" }, "favicon": { "type": [ "string", "null" ], "description": "Path or URL to the dealer's interface favicon.", "example": "paas/5001/custom.ico" }, "logo": { "type": [ "string", "null" ], "description": "Path or URL to the dealer's logotype.", "example": "paas/5001/logo.png" }, "subpaas": { "type": "boolean", "description": "`true` if this dealer is itself a sub-dealer of another.", "example": false }, "allow_branding": { "type": "boolean", "description": "`true` if the dealer's plan permits branding customization.", "example": true }, "password_policy": { "$ref": "#/components/schemas/PasswordPolicy" }, "paas_activation_date": { "type": [ "string", "null" ], "description": "Date the activation payment was made.", "format": "date", "example": "2015-03-01" }, "license_balance": { "type": "number", "description": "Current license balance.", "example": 0 }, "seller_currency": { "type": "string", "description": "Currency the seller bills this dealer in.", "example": "USD" }, "features": { "type": "array", "description": "Enabled dealer features.", "items": { "type": "string" }, "example": [ "branding_web", "branding_mobile", "navixy_label", "tracking", "reports", "fleet", "field_service", "premium_gis" ] }, "default_user_time_zone": { "type": "string", "description": "Time zone ID applied to users created through the user upload operation, and preselected when creating a user in the Admin Panel.", "example": "Europe/London" }, "standalone_token": { "type": "string", "description": "Service token, present only on standalone (on-premise) installations. Omitted entirely on Navixy-hosted platforms.", "readOnly": true } } }, "PaasTariff": { "type": "object", "description": "The PaaS plan a dealer is on.", "readOnly": true, "properties": { "id": { "type": "integer", "description": "Plan ID.", "example": 5 }, "name": { "type": "string", "description": "Plan name.", "example": "PaaS Tariff" }, "type": { "type": "string", "description": "Billing period type.", "example": "daily" }, "algorithm": { "type": "string", "description": "Charging algorithm applied by this plan.", "example": "plain" }, "gis_package": { "type": "string", "description": "GIS package included with this plan.", "example": "premium" }, "currency": { "type": "string", "description": "Plan currency.", "example": "RUB" }, "license_price": { "type": [ "number", "null" ], "description": "Price per license.", "example": null }, "min_license_pay": { "type": [ "number", "null" ], "description": "Minimum license payment.", "example": null }, "vat": { "type": "boolean", "description": "`true` if prices include VAT.", "example": false }, "trial": { "type": "boolean", "description": "`true` if this is a trial plan.", "example": false }, "premium_gis": { "type": "boolean", "description": "`true` if premium GIS is enabled.", "example": true }, "service_prices": { "allOf": [ { "$ref": "#/components/schemas/ServicePrices" } ], "description": "Per-unit prices for chargeable services on the dealer's own PaaS plan." }, "store_period": { "type": "string", "description": "Maximum data store period for users, as an ISO 8601 duration.", "example": "P3Y" } } }, "NotificationSettings": { "type": "object", "description": "Originators the platform uses when sending email, SMS, and voice notifications to a dealer's end users.", "properties": { "email_from": { "type": "string", "description": "Address notification email is sent from. Either a bare address or an address with a display name.", "example": "Navixy ", "maxLength": 100 }, "email_footer": { "type": "string", "description": "Footer appended to all notification emails.", "maxLength": 600, "example": "\n\nSincerely, Navixy" }, "email_special": { "type": [ "string", "null" ], "description": "Optional. Address used for PaaS reports. The only field of this object that may be omitted, in which case it is cleared. Also exposed by the service settings operations, where it is the same underlying value.", "example": "no-reply@navixy.com", "maxLength": 255 }, "sms_originator": { "type": "string", "description": "Originator shown on SMS notifications. Must match the pattern `(\\p{L}|\\d|[-'\" .,:/])*`.", "maxLength": 20, "example": "demo.navixy.com" }, "caller_id": { "type": "string", "description": "Originator shown on voice notifications. Must match the pattern `(\\p{L}|\\d|[-'\" .,:/])*`.", "maxLength": 20, "example": "491761234543" } } }, "DefaultMap": { "type": "object", "description": "The map, position, and zoom the monitoring interface opens on.", "properties": { "type": { "type": "string", "description": "Map code. Must be one of the maps listed in `maps`.", "example": "roadmap" }, "location": { "$ref": "#/components/schemas/Location" }, "zoom": { "type": "integer", "description": "Zoom level.", "example": 2 } } }, "DefaultUserSettings": { "type": "object", "description": "Settings applied by default to the dealer's newly created end users.", "properties": { "geocoder": { "type": "string", "description": "Default geocoder.", "example": "google" }, "route_provider": { "type": "string", "description": "Default route provider.", "example": "osrm" }, "measurement_system": { "type": "string", "description": "Measurement system.", "enum": [ "metric", "imperial" ], "example": "metric" }, "date_format": { "type": "string", "description": "Date representation.", "example": "ddMMyyyy_dots" }, "hour_mode": { "type": "string", "description": "Time representation.", "enum": [ "TWELVE_HOURS", "TWENTY_FOUR_HOURS" ], "example": "TWENTY_FOUR_HOURS" }, "translit": { "type": "boolean", "description": "When `true`, transliterates SMS text, replacing national alphabet characters with close Latin ones to reduce message length.", "example": false }, "default_hide_device_id": { "type": "boolean", "description": "When `true`, the web interface hides device IMEIs from the dealer's end users. Applies to every user who has no `hide_device_id` of their own, including users created before this value was changed.", "example": false } } }, "ServiceSettings": { "type": "object", "description": "A dealer's service settings, as returned by the service settings read operation. Branding image paths are read-only here and are changed through the branding image operations.", "properties": { "service_title": { "type": "string", "description": "Name of the service.", "example": "monitoring service" }, "locale": { "type": "string", "description": "Dealer's default locale.", "example": "en_US" }, "demo_login": { "type": "string", "description": "Login the demo button authenticates with. Demo access is disabled when empty.", "example": "demo" }, "demo_password": { "type": "string", "description": "Password the demo button authenticates with. Demo access is disabled when empty.", "example": "demo" }, "maps": { "type": "array", "description": "Maps available in the monitoring interface, chosen from `allowed_maps`. Only free maps are available when the domain is a subdomain of the platform owner. Observed codes include `roadmap`, `satellite`, `hybrid`, `terrain`, `yandex`, `osm`, `osmmapnik`, `wikimapia`, `cdcom`, `doublegis`, `bing`, `bing_satellite`, `bing_hybrid`, and `kosmosnimki`.", "items": { "type": "string" }, "example": [ "roadmap", "satellite", "osm", "osmmapnik" ] }, "default_map": { "$ref": "#/components/schemas/DefaultMap" }, "currency": { "type": "string", "description": "Currency code shown in the interface.", "example": "EUR" }, "payment_link": { "type": [ "string", "null" ], "description": "Link to the dealer's payment system.", "example": "http://payme.ru" }, "promo_url": { "type": [ "string", "null" ], "description": "Customizable \"About company\" URL.", "example": "http://monitoring.com/about" }, "google_client_id": { "type": "string", "description": "Google Maps client ID. Not yet supported by the interface.", "example": "io54p54ijy54" }, "domain": { "type": "string", "description": "Domain the monitoring interface is served on.", "example": "track.agent.com" }, "favicon": { "type": [ "string", "null" ], "description": "Path or URL to the interface favicon. Read-only here.", "example": "http://test.com/favicon.ico" }, "app_logo": { "type": [ "string", "null" ], "description": "Path or URL to the mobile app logotype. Read-only here.", "example": "paas/5001/app_logo.png" }, "logo": { "type": [ "string", "null" ], "description": "Path or URL to the dealer logotype. Read-only here.", "example": "paas/5001/logo.png" }, "document_logo": { "type": [ "string", "null" ], "description": "Path or URL to the logotype used in generated documents. Read-only here.", "example": "paas/5001/document_logo.png" }, "login_wallpaper": { "type": [ "string", "null" ], "description": "Path or URL to the login page wallpaper. Read-only here.", "example": "paas/5001/login.png" }, "desktop_wallpaper": { "type": [ "string", "null" ], "description": "Path to the interface wallpaper. Read-only here.", "example": "http://test.com/test.jpg" }, "login_footer": { "type": [ "string", "null" ], "description": "Footer shown on the login page.", "example": "All rights reserved." }, "allow_registration": { "type": "boolean", "description": "When `true`, end users may register themselves.", "example": true }, "show_mobile_apps": { "type": "boolean", "description": "When `true`, prompts visitors on mobile devices to install the mobile app rather than continue in the mobile web interface.", "example": true }, "default_user_settings": { "$ref": "#/components/schemas/DefaultUserSettings" }, "display_model_features_link": { "type": "boolean", "description": "When `true`, shows a link to navixy.com in device model information.", "example": false }, "limited_domain": { "type": "boolean", "description": "`true` if the PaaS domain has limitations.", "example": false }, "allowed_maps": { "type": "array", "description": "Maps the dealer may choose to include in `maps`. Set by the platform owner, not writable by the dealer.", "items": { "type": "string" }, "example": [ "roadmap", "satellite", "hybrid", "terrain", "osm", "osmmapnik", "wikimapia", "cdcom", "doublegis", "yandex", "bing", "bing_satellite", "bing_hybrid", "kosmosnimki" ] }, "color_theme": { "type": "string", "description": "Interface colour theme code. Empty string selects the default theme.", "maxLength": 128, "example": "aqua" }, "app_color_theme": { "type": "string", "description": "Mobile app colour theme code. Empty string selects the default theme.", "maxLength": 128, "example": "blue_1" }, "privacy_policy_link": { "type": [ "string", "null" ], "description": "Link to the privacy policy.", "example": "http://privacy-policy-url" }, "tos": { "type": [ "string", "null" ], "description": "Terms of service text.", "example": "Terms Of Service text" }, "no_register_commands": { "type": "boolean", "description": "When `true`, the platform does not send configuration commands to devices on activation.", "example": false }, "default_user_time_zone": { "type": "string", "description": "Time zone ID applied to users created through the user upload operation, and preselected when creating a user in the Admin Panel.", "example": "Europe/London" }, "email_special": { "type": "string", "description": "Address used for PaaS reports. Also returned by the notification settings read operation.", "example": "no-reply@navixy.com" }, "monitoring_logo": { "type": [ "string", "null" ], "description": "Path or URL to the logotype shown inside the monitoring interface. Read-only here.", "example": null }, "monitoring_logo_clickable": { "type": "boolean", "description": "When `true`, the monitoring interface logotype links to the dealer's promo URL.", "example": true }, "has_https": { "type": "boolean", "description": "`true` if the dealer's domain is served over HTTPS.", "example": true }, "no_auto_create_rules": { "type": "boolean", "description": "When `true`, the platform does not create default rules for newly registered devices.", "example": true }, "no_auto_create_sensors": { "type": "boolean", "description": "When `true`, the platform does not create default sensors for newly registered devices.", "example": false }, "display_release_notes": { "type": "boolean", "description": "When `true`, release notes are shown to end users.", "example": true }, "show_call_notifications": { "type": "boolean", "description": "When `true`, call notifications are shown in the end user interface.", "example": false }, "captcha_provider": { "type": "string", "description": "CAPTCHA provider used on registration and login forms.", "example": "internal" }, "gis_package": { "type": "string", "description": "GIS package active for this dealer.", "example": "premium" }, "gis_package_definition": { "type": [ "object", "null" ], "description": "Detailed definition of the active GIS package, or `null` when the package is a standard one.", "example": null }, "geocoders": { "type": "array", "description": "Geocoders available for selection. Empty when the platform defaults apply.", "items": { "type": "string" } }, "route_providers": { "type": "array", "description": "Route providers available for selection. Empty when the platform defaults apply.", "items": { "type": "string" } }, "lbs_providers": { "type": "array", "description": "Location-by-cell-tower providers available for selection. Empty when the platform defaults apply.", "items": { "type": "string" } }, "matrix_providers": { "type": "array", "description": "Distance matrix providers available for selection. Empty when the platform defaults apply.", "items": { "type": "string" } }, "information_center": { "$ref": "#/components/schemas/InformationCenter" } } }, "InformationCenter": { "type": "object", "description": "Visibility and source of the help content panels shown to end users.", "properties": { "release_notes": { "$ref": "#/components/schemas/InformationCenterSection" }, "user_guides": { "$ref": "#/components/schemas/InformationCenterSection" } } }, "InformationCenterSection": { "type": "object", "description": "One information centre panel.", "properties": { "visible": { "type": "boolean", "description": "`true` if the panel is shown to end users.", "example": true }, "content": { "type": "object", "description": "Where the panel's content comes from.", "properties": { "type": { "type": "string", "description": "Content source. `default` uses Navixy-supplied content.", "example": "default" } } } } }, "ServiceSettingsUpdate": { "type": "object", "description": "The writable subset of a dealer's service settings. Branding images, that is wallpapers, logos, and favicons, are absent by design and are changed through the branding image operations instead.", "properties": { "service_title": { "type": "string", "description": "Name of the service.", "example": "monitoring service", "maxLength": 100 }, "demo_login": { "type": "string", "description": "Login the demo button authenticates with. Demo access is disabled when empty.", "example": "demo", "maxLength": 50 }, "demo_password": { "type": "string", "description": "Password the demo button authenticates with. Demo access is disabled when empty.", "example": "demo", "maxLength": 50 }, "maps": { "type": "array", "description": "Maps available in the monitoring interface. Must be a subset of `allowed_maps` as returned by the service settings read operation.", "items": { "type": "string" }, "example": [ "roadmap", "satellite", "osm", "osmmapnik" ] }, "default_map": { "$ref": "#/components/schemas/DefaultMap" }, "currency": { "type": "string", "description": "Currency code shown in the interface.", "example": "EUR" }, "payment_link": { "type": [ "string", "null" ], "description": "Link to the dealer's payment system.", "example": "http://payme.ru", "format": "uri" }, "promo_url": { "type": [ "string", "null" ], "description": "Customizable \"About company\" URL.", "example": "http://monitoring.com/about", "format": "uri" }, "google_client_id": { "type": "string", "description": "Google Maps client ID.", "example": "io54p54ijy54" }, "domain": { "type": "string", "description": "Domain the monitoring interface is served on. Must not already be used by another dealer.", "example": "track.agent.com", "maxLength": 255 }, "login_footer": { "type": [ "string", "null" ], "description": "Footer shown on the login page.", "example": "All rights reserved." }, "allow_registration": { "type": "boolean", "description": "When `true`, end users may register themselves.", "example": true }, "show_mobile_apps": { "type": "boolean", "description": "When `true`, prompts visitors on mobile devices to install the mobile app.", "example": true }, "default_user_settings": { "$ref": "#/components/schemas/DefaultUserSettings" }, "display_model_features_link": { "type": "boolean", "description": "When `true`, shows a link to navixy.com in device model information.", "example": false }, "color_theme": { "type": "string", "description": "Interface colour theme code. Empty string selects the default theme.", "maxLength": 128, "example": "aqua" }, "app_color_theme": { "type": "string", "description": "Mobile app colour theme code. Empty string selects the default theme.", "maxLength": 128, "example": "blue_1" }, "privacy_policy_link": { "type": [ "string", "null" ], "description": "Link to the privacy policy.", "example": "http://privacy-policy-url", "maxLength": 200 }, "tos": { "type": [ "string", "null" ], "description": "Terms of service text.", "example": "Terms Of Service text", "maxLength": 20000 }, "no_register_commands": { "type": "boolean", "description": "When `true`, the platform does not send configuration commands to devices on activation.", "example": false }, "default_user_time_zone": { "type": "string", "description": "Time zone ID applied to newly created users.", "example": "Europe/London" }, "email_special": { "type": [ "string", "null" ], "description": "Address used for PaaS reports. Writable here as well as through the notification settings update, where it is the same underlying value. Omitting it clears it.", "example": "no-reply@navixy.com", "maxLength": 255 }, "no_auto_create_rules": { "type": "boolean", "description": "When `true`, the platform does not create default rules for newly registered devices. Omitting it resets it to `false`.", "example": true }, "locale": { "type": "string", "description": "Dealer's default locale.", "example": "en_US" }, "monitoring_logo_clickable": { "type": "boolean", "description": "When `true`, the monitoring interface logotype links to the dealer's promo URL.", "example": true } }, "required": [ "domain", "service_title", "locale", "demo_login", "demo_password", "maps", "default_map", "currency", "color_theme", "app_color_theme" ] }, "TimeZone": { "type": "object", "description": "A supported time zone.", "readOnly": true, "properties": { "zone_id": { "type": "string", "description": "Time zone ID, used throughout the API wherever a time zone is accepted.", "example": "America/Tijuana" }, "description": { "type": "string", "description": "Localized name of the zone, in the requested `locale`.", "example": "Tijuana" }, "base_offset": { "type": "number", "description": "Standard offset from UTC in hours, excluding DST. May be negative and may be fractional, for example `5.5`.", "example": -8 }, "dst_offset": { "type": "integer", "description": "Additional offset in hours applied while DST is in effect. `0` when the zone has no DST rules or is not currently observing them.", "example": 1 }, "country_code": { "type": "string", "description": "ISO 3166-1 alpha-2 country code for the zone.", "example": "MX" }, "alt_ids": { "type": "array", "description": "Alternative IDs that resolve to the same zone. Omitted entirely when there are none.", "items": { "type": "string" }, "example": [ "America/Ensenada", "America/Santa_Isabel" ] } } }, "Order": { "type": "object", "description": "An equipment order placed by the dealer. Null fields are omitted from the response.", "readOnly": true, "properties": { "id": { "type": "integer", "description": "Order ID.", "example": 3 }, "user_id": { "type": "integer", "description": "ID of the user the order belongs to.", "example": 11346 }, "seller_id": { "type": "integer", "description": "ID of the seller the order was placed with.", "example": 1 }, "type": { "type": "string", "description": "Order type.", "enum": [ "bank", "equip", "bank_service", "bank_license", "bank_license_camera" ], "example": "equip" }, "status": { "type": "string", "description": "Order status.", "enum": [ "created", "settled", "gathered", "shipped", "shipped_partially", "canceled" ], "example": "created" }, "amount": { "type": "integer", "description": "Number of items ordered.", "example": 1 }, "sum": { "type": "number", "description": "Order total.", "example": 34300 }, "with_vat": { "type": "boolean", "description": "Whether the total includes VAT." }, "payer": { "type": "string", "description": "Payer name.", "example": "Leonard Bernstein" }, "recipient": { "type": "string", "description": "Recipient name.", "example": "Leonard Bernstein" }, "contacts": { "type": "string", "description": "Recipient contact details.", "example": "" }, "place": { "type": "string", "description": "Delivery address.", "example": "111111 Leipzig, Leipzig Tieckstrasse, 2" }, "comment": { "type": "string", "description": "Free-text comment.", "example": "" }, "remark": { "type": "string", "description": "Additional remark. Omitted when empty." }, "link": { "type": "string", "description": "Link associated with the order." }, "creation_time": { "type": "string", "description": "When the order was created, as `YYYY-MM-DD HH:MM:SS`.", "example": "2009-12-10 01:00:36" }, "positions": { "type": "array", "description": "Line items of the order.", "items": { "$ref": "#/components/schemas/OrderPosition" } } } }, "OrderPosition": { "type": "object", "description": "A line item of an order.", "readOnly": true, "properties": { "id": { "type": "integer", "description": "Position ID." }, "order_id": { "type": "integer", "description": "ID of the parent order." }, "equip_id": { "type": "integer", "description": "ID of the equipment model ordered. The equipment catalogue is not exposed by this API, so this ID is only meaningful when matched against an order placed through the Admin Panel." }, "type": { "type": "string", "description": "Position type." }, "name": { "type": "string", "description": "Display name of the ordered item." }, "amount": { "type": "integer", "description": "Quantity." }, "price": { "type": "number", "description": "Unit price." } } }, "DealerOwnEmailGateway": { "type": "object", "description": "An email gateway owned by the dealer. Only the SMTP provider is currently supported.", "readOnly": true, "properties": { "id": { "type": "integer", "description": "Gateway ID.", "example": 2 }, "leasable": { "type": "boolean", "description": "Whether this dealer offers the gateway for lease to sub-dealers.", "example": false }, "label": { "type": "string", "description": "Display label.", "example": "Paas gate" }, "provider": { "type": "string", "description": "Gateway provider. Own gateways currently support `smtp` only.", "example": "smtp" }, "params": { "type": "object", "description": "Provider-specific configuration. For SMTP this carries `default_from_address` plus the `mail.smtp.*` transport settings. Contents vary by provider, so the shape is not fixed.", "additionalProperties": true } } }, "LeasableEmailGateway": { "type": "object", "description": "An email gateway offered for lease by the platform owner.", "readOnly": true, "properties": { "id": { "type": "integer", "description": "Gateway ID.", "example": 1 }, "label": { "type": "string", "description": "Display label.", "example": "Platform gate" }, "provider": { "type": "string", "description": "Gateway provider. Values observed include `router` and `mandrill_smtp`, so this is not limited to `smtp`.", "example": "router" }, "default_from_address": { "type": "string", "description": "Address mail from this gateway is sent from.", "example": "no-reply@domain.tld" } } }, "SubpaasListEntry": { "type": "object", "description": "A sub-dealer as returned by the list operation, with its user and device counts. Carries fewer fields than the read operation.", "readOnly": true, "properties": { "subpaas_id": { "type": "integer", "description": "Sub-dealer ID.", "example": 18 }, "title": { "type": "string", "description": "Sub-dealer display name.", "example": "SubppaasTitle" }, "jur_name": { "type": "string", "description": "Legal company name.", "example": "SubppaasJurName" }, "login": { "type": "string", "description": "Sub-dealer's panel login.", "example": "subpaaslogin" }, "creation_date": { "type": "string", "format": "date", "description": "When the sub-dealer was created.", "example": "2018-11-15" }, "block_type": { "type": "string", "description": "Block status of the sub-dealer panel and its users.", "enum": [ "NOT_BLOCKED", "INITIAL_BLOCK", "BLOCK_LOGIN", "CLIENTS_BLOCKED" ], "example": "NOT_BLOCKED" }, "users_count": { "type": "integer", "description": "Number of the sub-dealer's users.", "readOnly": true, "example": 2 }, "active_users_count": { "type": "integer", "description": "Number of the sub-dealer's active users.", "readOnly": true, "example": 1 }, "trackers_count": { "type": "integer", "description": "Total number of the sub-dealer's devices.", "readOnly": true, "example": 0 }, "active_trackers_count": { "type": "integer", "description": "Number of the sub-dealer's active devices.", "readOnly": true, "example": 0 } } }, "Subpaas": { "type": "object", "description": "A sub-dealer, also called a Sub-PaaS account: a dealer operating underneath another dealer.", "readOnly": true, "properties": { "subpaas_id": { "type": "integer", "description": "Sub-dealer ID.", "example": 18 }, "block_type": { "type": "string", "description": "Block status of the sub-dealer panel and its users.", "enum": [ "NOT_BLOCKED", "INITIAL_BLOCK", "BLOCK_LOGIN", "CLIENTS_BLOCKED" ], "example": "NOT_BLOCKED" }, "creation_date": { "type": "string", "format": "date", "description": "When the sub-dealer was created.", "example": "2018-11-15" }, "login": { "type": "string", "description": "Sub-dealer's panel login.", "example": "subpaaslogin" }, "title": { "type": "string", "description": "Sub-dealer display name.", "example": "Rus Sub-PaaS" }, "jur_name": { "type": "string", "description": "Legal company name.", "example": "OOO Sub-PaaS" }, "email": { "type": "string", "format": "email", "description": "Company email address.", "example": "sub-dealer@email.com" }, "jur_country": { "type": "string", "description": "Sub-dealer's country.", "example": "country" }, "link_monitoring": { "type": "string", "description": "Sub-dealer's monitoring domain.", "example": "link" }, "contact_fio": { "type": "string", "description": "Contact person.", "example": "fio" }, "contact_post": { "type": "string", "description": "Contact person position.", "example": "post" }, "contact_phone": { "type": "string", "description": "Contact person's phone.", "example": "phone" }, "users_count": { "type": "integer", "description": "Number of the sub-dealer's users.", "readOnly": true, "example": 2 }, "active_users_count": { "type": "integer", "description": "Number of the sub-dealer's active users.", "readOnly": true, "example": 1 }, "trackers_count": { "type": "integer", "description": "Total number of the sub-dealer's devices.", "readOnly": true, "example": 0 }, "active_trackers_count": { "type": "integer", "description": "Number of the sub-dealer's active devices.", "readOnly": true, "example": 0 } } }, "ServicePrices": { "type": "object", "description": "Per-unit prices for chargeable services.", "properties": { "incoming_sms": { "type": "number", "description": "Price per incoming SMS.", "example": 0.3 }, "outgoing_sms": { "type": "number", "description": "Price per outgoing SMS.", "example": 0.3 }, "service_sms": { "type": "number", "description": "Price per service SMS.", "example": 0.2 }, "traffic": { "type": "number", "description": "Price per 1 MB of traffic.", "example": 0.09 } } }, "MapFilter": { "type": "object", "description": "Restricts which maps the plan may use.", "properties": { "exclusion": { "type": "boolean", "description": "When `true`, `values` lists the maps to exclude. When `false`, it lists the only maps allowed.", "example": true }, "values": { "type": "array", "description": "Map codes the filter applies to.", "items": { "type": "string" }, "example": [] } } }, "Plan": { "type": "object", "description": "A service plan offered to a dealer's users. Called a plan in the interface and a tariff in the API paths.", "readOnly": true, "properties": { "id": { "type": "integer", "description": "Plan ID.", "example": 12163 }, "name": { "type": "string", "description": "Plan name.", "example": "Premium" }, "group_id": { "type": "integer", "description": "Plan group number.", "example": 3 }, "active": { "type": "boolean", "description": "`true` if a user is allowed to switch their current plan to this one.", "example": true }, "type": { "type": "string", "description": "Billing type. `activeday` applies to the `tracker` device type only.", "enum": [ "monthly", "activeday" ], "example": "monthly" }, "price": { "type": "number", "description": "Subscription price, usually per month.", "example": 12.55 }, "early_change_price": { "type": [ "number", "null" ], "description": "Price of switching from this plan to another less than 30 days after the last change, governed by the `tariff.freeze.period` config option. When absent or `null`, users cannot change plan frequently.", "example": 23 }, "device_limit": { "type": "integer", "description": "Maximum devices per user. Not used for cameras or sockets.", "example": 2000 }, "has_reports": { "type": "boolean", "description": "`true` if the plan includes reports.", "example": true }, "store_period": { "type": "string", "description": "Data storage period, as a short duration: `2h`, `3d`, `5m`, `1y`. Note this differs from the ISO 8601 form used by `store_period` on the dealer object.", "example": "1y" }, "proportional_charge": { "type": "boolean", "description": "When `true`, the monthly fee is reduced if the device was blocked during the month. Applies to `monthly` plans only.", "example": false }, "auto_prolong": { "type": "boolean", "description": "When `true`, the plan renews automatically.", "example": true }, "features": { "type": "array", "description": "Platform features the plan grants.", "items": { "type": "string" }, "example": [ "api", "event_notification", "report_xls", "routing" ] }, "map_filter": { "$ref": "#/components/schemas/MapFilter" }, "service_prices": { "$ref": "#/components/schemas/ServicePrices" }, "device_type": { "type": "string", "description": "Device type the plan applies to.", "enum": [ "tracker", "camera", "socket" ], "example": "tracker" } } }, "PlanDraft": { "type": "object", "description": "A plan definition for creation. Carries no `id`, which the platform assigns.", "properties": { "name": { "type": "string", "description": "Plan name.", "example": "Premium" }, "group_id": { "type": "integer", "description": "Plan group number.", "example": 3 }, "active": { "type": "boolean", "description": "`true` if a user is allowed to switch their current plan to this one.", "example": true }, "type": { "type": "string", "description": "Billing type. `activeday` applies to the `tracker` device type only.", "enum": [ "monthly", "activeday" ], "example": "monthly" }, "price": { "type": "number", "description": "Subscription price, usually per month.", "example": 12.55 }, "early_change_price": { "type": [ "number", "null" ], "description": "Price of switching from this plan to another less than 30 days after the last change, governed by the `tariff.freeze.period` config option. When absent or `null`, users cannot change plan frequently.", "example": 23 }, "device_limit": { "type": "integer", "description": "Maximum devices per user. Not used for cameras or sockets.", "example": 2000 }, "has_reports": { "type": "boolean", "description": "`true` if the plan includes reports.", "example": true }, "store_period": { "type": "string", "description": "Data storage period, as a short duration: `2h`, `3d`, `5m`, `1y`. Note this differs from the ISO 8601 form used by `store_period` on the dealer object.", "example": "1y" }, "proportional_charge": { "type": "boolean", "description": "When `true`, the monthly fee is reduced if the device was blocked during the month. Applies to `monthly` plans only.", "example": false }, "auto_prolong": { "type": "boolean", "description": "When `true`, the plan renews automatically.", "example": true }, "features": { "type": "array", "description": "Platform features the plan grants.", "items": { "type": "string" }, "example": [ "api", "event_notification", "report_xls", "routing" ] }, "map_filter": { "$ref": "#/components/schemas/MapFilter" }, "service_prices": { "$ref": "#/components/schemas/ServicePrices" }, "device_type": { "type": "string", "description": "Device type the plan applies to.", "enum": [ "tracker", "camera", "socket" ], "example": "tracker" } } }, "PlanEdit": { "type": "object", "description": "A plan definition for update. Requires `id` and omits `device_type`, which cannot change after creation.", "required": [ "id" ], "properties": { "id": { "type": "integer", "description": "ID of the plan to update.", "example": 12163 }, "name": { "type": "string", "description": "Plan name.", "example": "Premium" }, "group_id": { "type": "integer", "description": "Plan group number.", "example": 3 }, "active": { "type": "boolean", "description": "`true` if a user is allowed to switch their current plan to this one.", "example": true }, "type": { "type": "string", "description": "Billing type. `activeday` applies to the `tracker` device type only.", "enum": [ "monthly", "activeday" ], "example": "monthly" }, "price": { "type": "number", "description": "Subscription price, usually per month.", "example": 12.55 }, "early_change_price": { "type": [ "number", "null" ], "description": "Price of switching from this plan to another less than 30 days after the last change, governed by the `tariff.freeze.period` config option. When absent or `null`, users cannot change plan frequently.", "example": 23 }, "device_limit": { "type": "integer", "description": "Maximum devices per user. Not used for cameras or sockets.", "example": 2000 }, "has_reports": { "type": "boolean", "description": "`true` if the plan includes reports.", "example": true }, "store_period": { "type": "string", "description": "Data storage period, as a short duration: `2h`, `3d`, `5m`, `1y`. Note this differs from the ISO 8601 form used by `store_period` on the dealer object.", "example": "1y" }, "proportional_charge": { "type": "boolean", "description": "When `true`, the monthly fee is reduced if the device was blocked during the month. Applies to `monthly` plans only.", "example": false }, "auto_prolong": { "type": "boolean", "description": "When `true`, the plan renews automatically.", "example": true }, "features": { "type": "array", "description": "Platform features the plan grants.", "items": { "type": "string" }, "example": [ "api", "event_notification", "report_xls", "routing" ] }, "map_filter": { "$ref": "#/components/schemas/MapFilter" }, "service_prices": { "$ref": "#/components/schemas/ServicePrices" } } }, "TariffDefaults": { "type": "object", "description": "Defaults applied when a device of a given type is registered.", "properties": { "tariff_id": { "type": "integer", "description": "ID of the default plan for this device type.", "example": 1234 }, "activation_bonus": { "type": "number", "description": "Money added to the bonus balance on device registration.", "example": 1.1 }, "free_days": { "type": "integer", "description": "Number of fee-free days after device registration.", "example": 14 }, "free_days_device_limit": { "type": [ "integer", "null" ], "description": "Maximum number of a user's activated devices that get the free period. `null` means no limit.", "example": 3 } } }, "User": { "type": "object", "readOnly": true, "description": "An end user of the dealer service. The response form is flat: every legal field is present regardless of `legal_type`, with empty strings where a field does not apply. The request form used by create and update is a discriminated union on `legal_type` instead.", "properties": { "id": { "type": "integer", "description": "User ID.", "example": 371356 }, "dealer_id": { "type": "integer", "description": "ID of the owning dealer.", "example": 28152 }, "login": { "type": "string", "description": "Login, an email address.", "example": "user@example.com" }, "activated": { "type": "boolean", "description": "`true` once the account has been activated.", "example": true }, "verified": { "type": "boolean", "description": "`true` if the email address has been verified.", "example": true }, "phone_verified": { "type": "boolean", "description": "`true` if the phone number has been verified.", "example": true }, "legal_type": { "type": "string", "description": "Legal status, which determines which legal fields below are meaningful.", "enum": [ "individual", "legal_entity", "sole_trader" ], "example": "individual" }, "first_name": { "type": "string", "description": "First name.", "example": "Demo" }, "middle_name": { "type": "string", "description": "Middle name.", "example": "" }, "last_name": { "type": "string", "description": "Last name.", "example": "User" }, "phone": { "type": "string", "description": "Phone number." }, "post_country": { "type": "string", "description": "Postal address country." }, "post_index": { "type": "string", "description": "Postal code." }, "post_region": { "type": "string", "description": "Postal address region." }, "post_city": { "type": "string", "description": "Postal address city." }, "post_street_address": { "type": "string", "description": "Postal street address." }, "registered_country": { "type": "string", "description": "Registered address country. Meaningful for `legal_entity` and `sole_trader`." }, "registered_index": { "type": "string", "description": "Registered postal code. Meaningful for `legal_entity` and `sole_trader`." }, "registered_region": { "type": "string", "description": "Registered address region. Meaningful for `legal_entity` and `sole_trader`." }, "registered_city": { "type": "string", "description": "Registered address city. Meaningful for `legal_entity` and `sole_trader`." }, "registered_street_address": { "type": "string", "description": "Registered street address. Meaningful for `legal_entity` and `sole_trader`." }, "legal_name": { "type": "string", "description": "Legal company name. Meaningful for `legal_entity`." }, "tin": { "type": "string", "description": "Taxpayer identification number. Meaningful for `legal_entity` and `sole_trader`." }, "iec": { "type": "string", "description": "Interbranch enterprise code. Meaningful for `legal_entity`." }, "state_reg_num": { "type": "string", "description": "State registration number. Meaningful for `legal_entity` and `sole_trader`." }, "okpo_code": { "type": "string", "description": "OKPO classifier code. Digits only when present. Meaningful for `legal_entity` and `sole_trader`." }, "balance": { "type": "number", "description": "Current account balance.", "example": 0 }, "bonus": { "type": "number", "description": "Current bonus balance.", "example": 0 }, "trackers_count": { "type": "integer", "description": "Number of trackers the user owns.", "example": 7 }, "menu_preset_id": { "type": [ "integer", "null" ], "description": "ID of the menu preset assigned to this user.", "example": 346 }, "hide_device_id": { "type": "boolean", "description": "When `true`, the web interface hides device IMEIs from this user. Falls back to `default_hide_device_id` in the dealer's service settings when the user has no value of their own.", "example": false }, "mfa_allowed": { "type": "boolean", "description": "`true` if multi-factor authentication is permitted for this user.", "example": false }, "creation_date": { "type": "string", "description": "When the account was created, as `YYYY-MM-DD HH:MM:SS`.", "example": "2024-11-25 15:27:31" }, "comment": { "type": "string", "description": "Free-text comment.", "maxLength": 255 } } }, "UserDiscount": { "type": "object", "description": "A discount applied to a user.", "properties": { "percent": { "type": "number", "description": "Discount percentage." }, "end_date": { "type": [ "string", "null" ], "description": "Date the discount expires.", "format": "date" }, "device_limit": { "type": [ "integer", "null" ], "description": "Minimum devices required for the discount to apply." } } }, "UserTransaction": { "type": "object", "readOnly": true, "description": "A balance transaction recorded against a user.", "properties": { "id": { "type": "integer", "description": "Transaction ID." }, "user_id": { "type": "integer", "description": "ID of the user." }, "amount": { "type": "number", "description": "Signed amount applied." }, "type": { "type": "string", "description": "Which balance the transaction applied to." }, "text": { "type": "string", "description": "Reason recorded with the transaction." }, "timestamp": { "type": "string", "description": "When the transaction was recorded, as `YYYY-MM-DD HH:MM:SS`." } } }, "UserIndividual": { "type": "object", "title": "individual", "description": "A private individual. Postal fields are mandatory but may be empty strings.", "required": [ "legal_type", "login", "first_name", "middle_name", "last_name", "post_city", "phone", "post_country", "post_region", "post_city", "post_street_address", "post_index" ], "properties": { "legal_type": { "type": "string", "description": "Legal status. Determines which shape this object takes.", "enum": [ "individual" ], "example": "individual" }, "login": { "type": "string", "description": "Login, which is an email address. Must be unique across the platform.", "example": "user@example.com" }, "first_name": { "type": "string", "description": "First name. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100 }, "middle_name": { "type": "string", "description": "Middle name. Required but may be empty. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100 }, "last_name": { "type": "string", "description": "Last name. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100 }, "phone": { "type": "string", "description": "Phone number, digits only. Required but may be empty.", "pattern": "[0-9]*", "maxLength": 15, "example": "491761234567" }, "birth_date": { "type": [ "string", "null" ], "description": "Date of birth. Not returned by the read operations.", "format": "date" }, "passport": { "type": [ "string", "null" ], "description": "Passport details. Not returned by the read operations." }, "menu_preset_id": { "type": [ "integer", "null" ], "description": "ID of the menu preset to assign. See the menu preset operations." }, "hide_device_id": { "type": "boolean", "description": "Optional. When `true`, the web interface hides device IMEIs from this user. Omitting it on update keeps the current value. A value equal to `default_hide_device_id` in the dealer's service settings drops the user's own value, so the user follows that default again.", "example": false }, "activated": { "type": "boolean", "description": "Whether the account is activated. Mandatory on update." }, "post_country": { "type": "string", "description": "Postal address country. Required but may be empty. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100 }, "post_region": { "type": "string", "description": "Postal address region. Required but may be empty. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100 }, "post_city": { "type": "string", "description": "Postal address city. Required but may be empty. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100 }, "post_street_address": { "type": "string", "description": "Postal street address. Required but may be empty. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 200 }, "post_index": { "type": "string", "description": "Postal code. Validated against the country format. Required but may be empty." } } }, "UserSoleTrader": { "type": "object", "title": "sole_trader", "description": "A sole trader. Adds registration details, and tightens the postal fields so they may no longer be empty.", "required": [ "legal_type", "login", "first_name", "middle_name", "last_name", "post_city", "phone", "post_country", "post_region", "post_city", "post_street_address", "post_index", "registered_country", "registered_region", "registered_city", "registered_street_address", "registered_index", "tin" ], "properties": { "legal_type": { "type": "string", "description": "Legal status. Determines which shape this object takes.", "enum": [ "sole_trader" ], "example": "sole_trader" }, "login": { "type": "string", "description": "Login, which is an email address. Must be unique across the platform.", "example": "user@example.com" }, "first_name": { "type": "string", "description": "First name. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100 }, "middle_name": { "type": "string", "description": "Middle name. Required but may be empty. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100 }, "last_name": { "type": "string", "description": "Last name. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100 }, "phone": { "type": "string", "description": "Phone number, digits only. Required but may be empty.", "pattern": "[0-9]*", "maxLength": 15, "example": "491761234567" }, "birth_date": { "type": [ "string", "null" ], "description": "Date of birth. Not returned by the read operations.", "format": "date" }, "passport": { "type": [ "string", "null" ], "description": "Passport details. Not returned by the read operations." }, "menu_preset_id": { "type": [ "integer", "null" ], "description": "ID of the menu preset to assign. See the menu preset operations." }, "hide_device_id": { "type": "boolean", "description": "Optional. When `true`, the web interface hides device IMEIs from this user. Omitting it on update keeps the current value. A value equal to `default_hide_device_id` in the dealer's service settings drops the user's own value, so the user follows that default again.", "example": false }, "activated": { "type": "boolean", "description": "Whether the account is activated. Mandatory on update." }, "post_country": { "type": "string", "description": "Postal address country. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100, "minLength": 1 }, "post_region": { "type": "string", "description": "Postal address region. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100, "minLength": 1 }, "post_city": { "type": "string", "description": "Postal address city. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100, "minLength": 1 }, "post_street_address": { "type": "string", "description": "Postal street address. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 200, "minLength": 1 }, "post_index": { "type": "string", "description": "Postal code. Validated against the country format. Must not be blank.", "minLength": 1 }, "registered_country": { "type": "string", "description": "Registered address country. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100, "minLength": 1 }, "registered_region": { "type": "string", "description": "Registered address region. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100, "minLength": 1 }, "registered_city": { "type": "string", "description": "Registered address city. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100, "minLength": 1 }, "registered_street_address": { "type": "string", "description": "Registered street address. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 200, "minLength": 1 }, "registered_index": { "type": "string", "description": "Registered postal code. Validated against the country format. Must not be blank.", "minLength": 1 }, "tin": { "type": "string", "description": "Taxpayer identification number. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 255 }, "state_reg_num": { "type": "string", "description": "State registration number. Digits only when not empty.", "maxLength": 15, "pattern": "\\d+|(^$)" }, "okpo_code": { "type": "string", "description": "OKPO classifier code. When not empty, must be 8 or 10 digits.", "pattern": "\\d{8,10}|(^$)" } } }, "UserLegalEntity": { "type": "object", "title": "legal_entity", "description": "A legal entity. Adds the company name and interbranch code on top of the sole trader fields.", "required": [ "legal_type", "login", "first_name", "middle_name", "last_name", "post_city", "phone", "post_country", "post_region", "post_city", "post_street_address", "post_index", "registered_country", "registered_region", "registered_city", "registered_street_address", "registered_index", "tin", "legal_name", "iec" ], "properties": { "legal_type": { "type": "string", "description": "Legal status. Determines which shape this object takes.", "enum": [ "legal_entity" ], "example": "legal_entity" }, "login": { "type": "string", "description": "Login, which is an email address. Must be unique across the platform.", "example": "user@example.com" }, "first_name": { "type": "string", "description": "First name. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100 }, "middle_name": { "type": "string", "description": "Middle name. Required but may be empty. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100 }, "last_name": { "type": "string", "description": "Last name. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100 }, "phone": { "type": "string", "description": "Phone number, digits only. Required but may be empty.", "pattern": "[0-9]*", "maxLength": 15, "example": "491761234567" }, "birth_date": { "type": [ "string", "null" ], "description": "Date of birth. Not returned by the read operations.", "format": "date" }, "passport": { "type": [ "string", "null" ], "description": "Passport details. Not returned by the read operations." }, "menu_preset_id": { "type": [ "integer", "null" ], "description": "ID of the menu preset to assign. See the menu preset operations." }, "hide_device_id": { "type": "boolean", "description": "Optional. When `true`, the web interface hides device IMEIs from this user. Omitting it on update keeps the current value. A value equal to `default_hide_device_id` in the dealer's service settings drops the user's own value, so the user follows that default again.", "example": false }, "activated": { "type": "boolean", "description": "Whether the account is activated. Mandatory on update." }, "post_country": { "type": "string", "description": "Postal address country. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100, "minLength": 1 }, "post_region": { "type": "string", "description": "Postal address region. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100, "minLength": 1 }, "post_city": { "type": "string", "description": "Postal address city. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100, "minLength": 1 }, "post_street_address": { "type": "string", "description": "Postal street address. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 200, "minLength": 1 }, "post_index": { "type": "string", "description": "Postal code. Validated against the country format. Must not be blank.", "minLength": 1 }, "registered_country": { "type": "string", "description": "Registered address country. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100, "minLength": 1 }, "registered_region": { "type": "string", "description": "Registered address region. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100, "minLength": 1 }, "registered_city": { "type": "string", "description": "Registered address city. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 100, "minLength": 1 }, "registered_street_address": { "type": "string", "description": "Registered street address. Must not be blank. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 200, "minLength": 1 }, "registered_index": { "type": "string", "description": "Registered postal code. Validated against the country format. Must not be blank.", "minLength": 1 }, "tin": { "type": "string", "description": "Taxpayer identification number. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 255 }, "state_reg_num": { "type": "string", "description": "State registration number. Digits only when not empty.", "maxLength": 15, "pattern": "\\d+|(^$)" }, "okpo_code": { "type": "string", "description": "OKPO classifier code. When not empty, must be 8 or 10 digits.", "pattern": "\\d{8,10}|(^$)" }, "legal_name": { "type": "string", "description": "Legal company name. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 255, "minLength": 1 }, "iec": { "type": "string", "description": "Interbranch enterprise code. Must match the platform name pattern: letters, digits, and the characters `- ' \" . , : /`.", "maxLength": 255 } } }, "UserEditForm": { "description": "A user to create or update. The shape depends on `legal_type`, which selects one of three variants.\n\nThe three are cumulative: a sole trader is an individual plus registration details, and a legal entity is a sole trader plus a company name and interbranch code. The legal variants also tighten the postal fields, which may be empty for an individual but not for a sole trader or legal entity.\n\nOn update, `id` and `activated` are both mandatory.", "oneOf": [ { "$ref": "#/components/schemas/UserIndividual" }, { "$ref": "#/components/schemas/UserSoleTrader" }, { "$ref": "#/components/schemas/UserLegalEntity" } ], "discriminator": { "propertyName": "legal_type", "mapping": { "individual": "#/components/schemas/UserIndividual", "sole_trader": "#/components/schemas/UserSoleTrader", "legal_entity": "#/components/schemas/UserLegalEntity" } } }, "MenuTab": { "type": "object", "description": "A single destination within a menu item. Titles are localization keys, not display strings.", "properties": { "title": { "type": "string", "description": "Localization key for the tab title.", "example": "common.menu.dashboard" }, "destination": { "type": "string", "description": "Application destination this tab opens.", "example": "dashboard" } } }, "MenuItem": { "type": "object", "description": "An entry in a menu group. An item with several tabs opens as a group of related destinations.", "properties": { "title": { "type": "string", "description": "Localization key for the item title.", "example": "common.menu.dashboard" }, "icon": { "type": "string", "description": "Icon identifier.", "example": "dashboard" }, "tabs": { "type": "array", "description": "Destinations belonging to this item.", "items": { "$ref": "#/components/schemas/MenuTab" } } } }, "MenuGroup": { "type": "object", "description": "A titled group of menu items. The title is frequently `null`, which renders the group without a heading.", "properties": { "title": { "type": [ "string", "null" ], "description": "Localization key for the group title, or `null` for an untitled group.", "example": null }, "items": { "type": "array", "description": "Items in the group.", "items": { "$ref": "#/components/schemas/MenuItem" } } } }, "MenuPreset": { "type": "object", "description": "A menu layout that can be assigned to users.\n\nNote the asymmetry: `main` is an **array** of groups, while `footer` is a **single** group.", "properties": { "id": { "type": "integer", "description": "Preset ID.", "example": 346 }, "title": { "type": "string", "description": "Preset name.", "example": "User Apps" }, "main": { "type": "array", "description": "Groups shown in the main menu area.", "items": { "$ref": "#/components/schemas/MenuGroup" } }, "footer": { "allOf": [ { "$ref": "#/components/schemas/MenuGroup" } ], "description": "The single group shown in the menu footer." } } }, "MenuPresetDraft": { "type": "object", "description": "A menu preset for creation. Carries no `id`, which the platform assigns.", "required": [ "title" ], "properties": { "title": { "type": "string", "description": "Preset name.", "example": "User Apps" }, "main": { "type": "array", "items": { "$ref": "#/components/schemas/MenuGroup" } }, "footer": { "$ref": "#/components/schemas/MenuGroup" } } }, "MenuPresetEdit": { "type": "object", "description": "A menu preset for update. Requires `id`.", "required": [ "id", "title" ], "properties": { "id": { "type": "integer", "description": "Menu preset ID.", "minimum": 1, "example": 346 }, "title": { "type": "string", "description": "Preset name.", "example": "User Apps" }, "main": { "type": "array", "items": { "$ref": "#/components/schemas/MenuGroup" } }, "footer": { "$ref": "#/components/schemas/MenuGroup" } } }, "MenuPresetAssignmentAll": { "type": "object", "title": "default", "description": "Assign the preset as the dealer default, applying to users with no explicit assignment.", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "default" ], "example": "default" } } }, "MenuPresetAssignmentUsers": { "type": "object", "title": "users", "description": "Assign the preset to an explicit list of users.", "required": [ "type", "ids" ], "properties": { "type": { "type": "string", "enum": [ "users" ], "example": "users" }, "ids": { "type": "array", "description": "User IDs to assign the preset to. At most 10000.", "maxItems": 10000, "items": { "type": "integer", "minimum": 1 }, "example": [ 371356 ] } } }, "MenuPresetAssignmentTarget": { "description": "What the preset is assigned to. The shape depends on `type`.", "oneOf": [ { "$ref": "#/components/schemas/MenuPresetAssignmentAll" }, { "$ref": "#/components/schemas/MenuPresetAssignmentUsers" } ], "discriminator": { "propertyName": "type", "mapping": { "default": "#/components/schemas/MenuPresetAssignmentAll", "users": "#/components/schemas/MenuPresetAssignmentUsers" } } }, "MenuPresetListEntry": { "type": "object", "description": "A menu preset together with who owns it and what it is assigned to.", "readOnly": true, "properties": { "preset": { "$ref": "#/components/schemas/MenuPreset" }, "owner": { "type": "string", "description": "Who defined the preset. Platform-owned presets are supplied by Navixy and are not editable by the dealer.", "enum": [ "dealer", "platform" ], "example": "dealer" }, "assignments": { "type": "array", "description": "Current assignments of this preset.", "items": { "$ref": "#/components/schemas/MenuPresetAssignmentTarget" } } } }, "MenuItemDestination": { "type": "object", "description": "A menu item available for use when composing a preset.", "readOnly": true, "properties": { "title": { "type": "string", "description": "Localization key for the item title.", "example": "common.menu.dashboard" }, "destination": { "type": "string", "description": "Application destination.", "example": "dashboard" } } }, "MfaSettingsAllowed": { "type": "object", "title": "allowed", "description": "Multi-factor authentication is permitted, using the listed factor types.", "required": [ "type", "factor_types" ], "properties": { "type": { "type": "string", "enum": [ "allowed" ], "example": "allowed" }, "factor_types": { "type": "array", "description": "Permitted authentication factors. Must not be empty. Only `email` is currently supported.", "minItems": 1, "items": { "type": "string", "enum": [ "email" ] }, "example": [ "email" ] } } }, "MfaSettingsDisallowed": { "type": "object", "title": "disallowed", "description": "Multi-factor authentication is not permitted.", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "disallowed" ], "example": "disallowed" } } }, "MfaSettings": { "description": "Multi-factor authentication policy. The shape depends on `type`.", "oneOf": [ { "$ref": "#/components/schemas/MfaSettingsAllowed" }, { "$ref": "#/components/schemas/MfaSettingsDisallowed" } ], "discriminator": { "propertyName": "type", "mapping": { "allowed": "#/components/schemas/MfaSettingsAllowed", "disallowed": "#/components/schemas/MfaSettingsDisallowed" } } }, "MfaTargetAll": { "type": "object", "title": "all", "description": "Apply to every user of the dealer.", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "all" ], "example": "all" } } }, "MfaTargetSelected": { "type": "object", "title": "selected", "description": "Apply to an explicit list of users.", "required": [ "type", "ids" ], "properties": { "type": { "type": "string", "enum": [ "selected" ], "example": "selected" }, "ids": { "type": "array", "description": "User IDs. Between 1 and 100 inclusive.", "minItems": 1, "maxItems": 100, "items": { "type": "integer", "minimum": 1 }, "example": [ 371356 ] } } }, "MfaTarget": { "description": "Which users the settings apply to. The shape depends on `type`.", "oneOf": [ { "$ref": "#/components/schemas/MfaTargetAll" }, { "$ref": "#/components/schemas/MfaTargetSelected" } ], "discriminator": { "propertyName": "type", "mapping": { "all": "#/components/schemas/MfaTargetAll", "selected": "#/components/schemas/MfaTargetSelected" } } }, "TrackerSource": { "type": "object", "description": "The physical device behind a tracker. Several operations act on the source rather than the tracker, and `raw_command/send` identifies it by `device_id`.", "readOnly": true, "properties": { "id": { "type": "integer", "description": "Source ID.", "example": 10336201 }, "device_id": { "type": "string", "description": "Device identifier, used by the raw command operation.", "example": "114038727861" }, "model": { "type": "string", "description": "Device model code.", "example": "navixymobile_xgps" }, "blocked": { "type": "boolean", "description": "Whether the device is blocked.", "example": false }, "phone": { "type": [ "string", "null" ], "description": "SIM phone number, or `null` for devices without one.", "example": null }, "tariff_id": { "type": "integer", "description": "ID of the plan the device is on.", "example": 21967 }, "tariff_end_date": { "type": [ "string", "null" ], "description": "When the current plan period ends.", "format": "date", "example": "2026-09-01" }, "connection_status": { "type": "string", "description": "Current connection state.", "example": "active" }, "creation_date": { "type": "string", "description": "When the source was created.", "format": "date", "example": "2024-11-25" } } }, "Tracker": { "type": "object", "description": "A tracker: a device as presented to one owning user. A clone shares its source with another tracker.", "readOnly": true, "properties": { "id": { "type": "integer", "description": "Tracker ID.", "example": 3234961 }, "label": { "type": "string", "description": "Display label.", "example": "Courier" }, "group_id": { "type": "integer", "description": "Group ID, `0` when ungrouped.", "example": 0 }, "user_id": { "type": "integer", "description": "ID of the owning user.", "example": 371356 }, "dealer_id": { "type": "integer", "description": "ID of the owning dealer.", "example": 28152 }, "owner_name": { "type": "string", "description": "Display name of the owning user.", "example": "User Demo" }, "source": { "$ref": "#/components/schemas/TrackerSource" }, "model_name": { "type": "string", "description": "Human-readable device model name.", "example": "X-GPS Tracker Android" }, "clone": { "type": "boolean", "description": "`true` if this tracker is a clone of another.", "example": false }, "deleted": { "type": "boolean", "description": "Whether the tracker is marked deleted.", "example": false }, "creation_date": { "type": "string", "description": "When the tracker was created.", "format": "date", "example": "2024-11-25" }, "last_connection": { "type": [ "string", "null" ], "description": "When the device last connected, as `YYYY-MM-DD HH:MM:SS`.", "example": "2026-08-04 10:25:55" } } }, "ActiveHistoryMonth": { "type": "object", "description": "Active tracker count for one month.", "readOnly": true, "properties": { "month": { "type": "string", "description": "The month, as `YYYY-MM`.", "example": "2026-07" }, "amount": { "type": "integer", "description": "Number of trackers active during the month.", "example": 1 }, "trackers": { "type": "array", "description": "The trackers counted. Owners are in `users_map` on the response.", "items": { "type": "object", "properties": { "tracker_id": { "type": "integer", "example": 3234961 }, "user_id": { "type": "integer", "example": 371356 }, "label": { "type": "string", "example": "Courier" }, "device_id": { "type": "string", "example": "114038727861" } } } } } } } } }