Logo Neyos

Neyos API

A secure REST API to query your trackers, send them commands and manage your webhooks from your own applications.

The Neyos API is a REST API that lets you drive your fleet from your own tools: check the state of your trackers, send them remote commands and manage the webhooks that feed your systems in real time.

Base URLhttps://api.neyos-equipment.com/api/v1
FormatJSON (UTF-8)
AuthenticationAuthorization: Bearer ctk_xxxxx on every request
ProtocolHTTPS only
Every returned resource is automatically scoped to your organization. Any attempt to access a resource belonging to another customer returns a 404 error — never the data itself.

Authentication

Every request must carry your customer token in the Authorization header:

curl https://api.neyos-equipment.com/api/v1/trackers \
  -H "Authorization: Bearer ctk_xxxxxxxxxxxxxxxxxxxxxxx"

A call without a token, or with an invalid, expired or revoked token, returns 401 Unauthorized.

Your ctk_… token grants access to your whole fleet. Keep it server-side, in a secret manager — never in front-end code, a Git repository or a mobile application.

Conventions

Identifiers

Trackers are referenced by their serial, the serial number engraved on the casing. Other resources carry a prefixed identifier:

PrefixResource
—Tracker — referenced by its serial
tac_TrackerAction (command)
end_Webhook (endpoint)

Dates

On the API, all dates are serialized as Unix milliseconds (number) or null.

Webhook notifications do not all use the same format: tracker.* and message.created events return ISO 8601 dates, while tracker_action.* events return milliseconds. See Date formats.

Pagination

List endpoints accept the following parameters:

ParameterTypeDefaultDescription
pageinteger1Page number
perPageinteger25Items per page (max 100)
sortstringvariesSort field
orderasc | descvariesSort order
searchstring—Text search (fields depend on the endpoint)

A paginated response always has the following shape:

{
  "meta": {
    "total": 142,
    "perPage": 25,
    "currentPage": 1,
    "lastPage": 6,
    "firstPage": 1
  },
  "data": [ ]
}

Models

Command types

Two command types can be created through the public API:

typeDescriptionRequired fields
custom_commandsSends a list of textual commandscommands: string[]
power_offPowers the tracker off—

Other types (load_config, send_config, time_sync…) are generated by the platform. They may appear in a tracker's history or in your webhooks, but cannot be created from the API.

Command states

statusMeaning
waiting_config_loadedWaiting for the tracker configuration to be loaded
waitingQueued, not transmitted yet
pendingTransmitted to the tracker, awaiting acknowledgement
receivedPartial acknowledgement received
successExecuted successfully
failedFailed after several attempts
canceledCanceled before execution
mergedMerged with another command

Typical life cycle: waiting → pending → received → success or failed.

Trackers

List trackers

GET /api/v1/trackers

Parameters: page, perPage, sort (default serial), order, search (filters on serial and alias).

Additional filters — several values can be separated by a comma:

ParameterValues
connectedtrue | false
chargingtrue | false
sleeptrue | false
zoneTracktrue | false
curl "https://api.neyos-equipment.com/api/v1/trackers?perPage=10&connected=true&search=depot" \
  -H "Authorization: Bearer ctk_xxxxx"

200 response — a paginated object containing an array of Tracker in data.

Retrieve a tracker

GET /api/v1/trackers/:serial

200 response — a Tracker object. 404 error — the tracker does not exist or does not belong to your organization.

Update a tracker

PATCH /api/v1/trackers/:serial

Only the alias and notes fields can be modified. Both are optional and can be set back to null.

{
  "alias": "Truck 12 - north depot",
  "notes": "Assigned to the Lyon-Grenoble route"
}

200 response — the updated tracker.

An update through this endpoint triggers a tracker.updated webhook event.

Command history of a tracker

GET /api/v1/trackers/:serial/actions

Parameters: page, perPage, sort (default createdAt), order (default desc).

FilterValues (several separated by ,)
statuswaiting, pending, received, success, failed, canceled, merged
typecustom_commands, power_off, load_config, send_config, time_sync

200 response — a paginated object of TrackerAction.

Commands

Send a command to a tracker

POST /api/v1/trackers/:serial/actions
FieldTypeRequiredDefault
type"custom_commands" | "power_off"yes—
commandsstring[]if type = custom_commands—
prioritynumber (1 to 100)no50
{
  "type": "custom_commands",
  "commands": ["gnss set --rate=5000", "modem set --network_1=0"],
  "priority": 50
}

201 response — the command has been created and queued:

{
  "status": "created",
  "data": { }
}

200 response — the tracker is already in the requested state, no command was created:

{
  "status": "already_up_to_date",
  "message": "Tracker is already up to date"
}

Errors: 404 (unknown tracker), 422 (validation).

A command is not executed immediately: it is transmitted the next time the tracker connects. Follow its progress through the tracker_action.updated webhook event, or by polling GET /api/v1/actions/:id.

Send commands to several trackers

POST /api/v1/actions/_bulk
{
  "trackerActions": [
    { "serial": "AB123", "type": "power_off" },
    { "serial": "AB124", "type": "custom_commands", "commands": ["gnss set --rate=10000"] },
    { "serial": "AB125", "type": "custom_commands", "commands": ["modem set --apn=mybiz"], "priority": 20 }
  ]
}

Each entry is processed independently: a single failure (tracker outside your organization, invalid command…) does not make the others fail.

201 response

{
  "total": 3,
  "created": 2,
  "failed": 1,
  "results": [
    { "index": 0, "status": "created", "id": "tac_xxx", "data": { } },
    { "index": 1, "status": "created", "id": "tac_yyy", "data": { } }
  ],
  "errors": [
    { "index": 2, "status": "error", "message": "Tracker not found", "input": { } }
  ]
}

The index field matches the position of the entry in the array you sent, so each result can be mapped back to its original request.

Track a command

GET /api/v1/actions/:id

200 response — a TrackerAction with its attempts relation: each send attempt contains sentAt, receivedAt and response.

Cancel a command

PUT /api/v1/actions/:id/cancel

A command can only be canceled as long as it has not been transmitted to the tracker, that is, while its status is waiting. A command already sent cannot be recalled.

200 response

{ "status": "canceled" }

Webhooks

Webhooks push your organization's events to the URL of your choice with POST. Every enabled webhook attached to your account receives each event.

For the server-side setup, the detailed payloads and complete examples, see the Webhook page.

List your webhooks

GET /api/v1/webhooks

Parameters: page, perPage, sort (default createdAt), order (default desc), search (filters on url).

Retrieve a webhook

GET /api/v1/webhooks/:id

Create a webhook

POST /api/v1/webhooks
FieldTypeRequiredDefault
urlstring (valid URL)yes—
descriptionstring | nullnonull
enabledbooleannotrue
{
  "url": "https://app.my-domain.com/integrations/neyos",
  "description": "Production webhook",
  "enabled": true
}

201 response — the created webhook, along with its signingSecret:

{
  "id": "end_xxx",
  "url": "https://app.my-domain.com/integrations/neyos",
  "description": "Production webhook",
  "enabled": true,
  "signingSecret": "whsec_2aB3cD...",
  "createdAt": 1737031800000,
  "updatedAt": 1737031800000
}
The signingSecret is returned only once, on creation. It appears in no other response. Store it in your secret manager straight away: if it is lost, the only option is to delete the webhook and create a new one.

Update a webhook

PUT /api/v1/webhooks/:id

Same fields as on creation, all optional: only the fields you provide are modified. 200 response — the updated webhook.

Delete a webhook

DELETE /api/v1/webhooks/:id

204 response — no content.

Event types

typeEmitted when…data contains
tracker.createdA tracker is attached to your organizationTracker
tracker.updatedA tracker's alias or notes are modifiedTracker
tracker.deletedA tracker is deletedTracker
tracker_action.createdA command is created (via the API or the platform)TrackerAction
tracker_action.updatedA command changes state (sent, acknowledged, success, failure…)TrackerAction
tracker_action.deletedA command is deletedTrackerAction
message.createdA new frame is received from a trackerMessage
tracker.updated is not emitted on every position or battery change: it is deliberately limited to alias and notes modifications. To follow a tracker's field activity, listen to message.created.

Every notification uses the same envelope:

{
  "type": "tracker.updated",
  "data": { }
}

Date formats

Date formats depend on the event — this is the main integration pitfall:

ContextFormat
REST API responsesUnix milliseconds
tracker.* and message.created eventsISO 8601 (2026-09-01T10:28:03.000+00:00)
tracker_action.* eventsUnix milliseconds
timestamp field of an element (point, event)Unix seconds

Delivery guarantees

  • Disabled webhooks (enabled: false) receive no calls.
  • Expected response: a 200 status code. Any other response, as well as a timeout or an unreachable host, is logged as a failure.
  • Calls are asynchronous, through a job queue: two notifications close in time may arrive out of order. Rely on the timestamps in the payload, not on the order of reception.
  • The same event may be received several times: use the X-Neyos-Event-Id header as an idempotency key.
  • Every notification is logged on the Neyos side (URL, body sent, HTTP status, response time, outcome), and the webhook's sentAt field is updated on each send.

Notification signature

Every outgoing webhook call is signed with HMAC-SHA256 using the signingSecret returned when the webhook was created, and carries the X-Neyos-Timestamp, X-Neyos-Signature and X-Neyos-Event-Id headers.

The computation formula, the verification procedure and Node.js / Python / PHP examples are detailed on the Webhook page.

Error codes

CodeTypical cases
200Success
201Resource created
204Success with no content (deletion)
401Missing, invalid, expired or revoked token
403Forbidden action
404Resource not found or belonging to another organization
422Validation error (invalid type, malformed url, empty commands…)
500Internal error

422 validation errors detail the offending fields:

{
  "errors": [
    { "message": "The url field must be a valid URL", "rule": "url", "field": "url" }
  ]
}

Need an access token or help with your integration?

Contact our support team to get your API credentials. contact@neyos.com