API Neyos
L'API Neyos est une API REST qui vous permet de piloter votre parc depuis vos propres outils : consulter l'état de vos balises, leur envoyer des commandes à distance et gérer les webhooks qui alimentent vos systèmes en temps réel.
| Base URL | https://api.neyos-equipment.com/api/v1 |
| Format | JSON (UTF-8) |
| Authentification | Authorization: Bearer ctk_xxxxx sur chaque requête |
| Protocole | HTTPS uniquement |
404, jamais les données concernées.Authentification
Chaque requête doit porter votre jeton client dans l'en-tête Authorization :
curl https://api.neyos-equipment.com/api/v1/trackers \
-H "Authorization: Bearer ctk_xxxxxxxxxxxxxxxxxxxxxxx"
Un appel sans jeton, ou avec un jeton invalide, expiré ou révoqué, renvoie 401 Unauthorized.
ctk_… donne accès à l'ensemble de votre parc. Conservez-le côté serveur, dans un gestionnaire de secrets — jamais dans un code front-end, un dépôt Git ou une application mobile.Conventions
Identifiants
Les balises sont référencées par leur serial, le numéro de série gravé sur le boîtier. Les autres ressources portent un identifiant préfixé :
| Préfixe | Ressource |
|---|---|
| — | Tracker — référencé par son serial |
tac_ | TrackerAction (commande) |
end_ | Webhook (endpoint) |
Dates
Sur l'API, toutes les dates sont sérialisées en millisecondes Unix (number) ou null.
tracker.* et message.created renvoient des dates ISO 8601, les événements tracker_action.* des millisecondes. Voir Format des dates.Pagination
Les endpoints de liste acceptent les paramètres suivants :
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
page | integer | 1 | Numéro de page |
perPage | integer | 25 | Éléments par page (max 100) |
sort | string | varie | Champ de tri |
order | asc | desc | varie | Ordre de tri |
search | string | — | Recherche textuelle (champs concernés selon l'endpoint) |
Une réponse paginée a toujours la forme suivante :
{
"meta": {
"total": 142,
"perPage": 25,
"currentPage": 1,
"lastPage": 6,
"firstPage": 1
},
"data": [ ]
}
Modèles
| Champ | Type | Description |
|---|---|---|
serial | string | Numéro de série physique (unique) — votre référence |
alias | string | null | Nom personnalisé donné à la balise |
notes | string | null | Notes libres |
network | string | null | Réseau utilisé (lte-m, gsm, nb-iot…) |
mcc / mnc | string | null | Mobile Country Code / Mobile Network Code |
rsrq | number | null | Qualité du signal |
battery | number | null | Niveau de batterie (%) |
temperature | number | null | Température (°C) |
latitude | number | null | Latitude WGS84 |
longitude | number | null | Longitude WGS84 |
altitude | number | null | Altitude (m) |
speed | number | null | Vitesse |
connected | boolean | Balise actuellement connectée |
connectedAt | number | null | Dernière connexion (ms) |
sleep | boolean | Balise en veille |
sleepAt | number | null | Entrée en veille (ms) |
charging | boolean | Balise en charge |
chargingAt | number | null | Début de charge (ms) |
sentAt | number | null | Dernière trame reçue (ms) |
lastPointAt | number | null | Dernier point GPS (ms) |
configSentAt | number | null | Dernier envoi de configuration (ms) |
zoneTrack | boolean | Suivi de zone (geofencing) actif |
createdAt | number | Date de création (ms) |
updatedAt | number | Dernière modification (ms) |
| Champ | Type | Description |
|---|---|---|
id | string (tac_…) | Identifiant unique de la commande |
serial | string | Numéro de série de la balise ciblée |
type | string | Nature de la commande (voir ci-dessous) |
payload | object | Commandes effectivement transmises à la balise |
priority | number | Priorité, de 1 (haute) à 100 (basse) |
status | string | État courant (voir ci-dessous) |
response | object | null | Accusé de réception retourné par la balise |
createdAt | number | Date de création (ms) |
updatedAt | number | Dernière mise à jour (ms) |
attempts | array | Historique des tentatives d'envoi — présent sur GET /actions/:id |
| Champ | Type | Description |
|---|---|---|
id | string (end_…) | Identifiant unique |
url | string | URL HTTP(S) appelée en POST |
description | string | null | Description libre |
enabled | boolean | Webhook activé ou désactivé |
sentAt | number | null | Date du dernier appel (ms) |
createdAt | number | Date de création (ms) |
updatedAt | number | Dernière modification (ms) |
Types de commandes
Deux types de commandes peuvent être créés via l'API publique :
type | Description | Champs requis |
|---|---|---|
custom_commands | Envoie une liste de commandes textuelles | commands: string[] |
power_off | Éteint la balise | — |
D'autres types (load_config, send_config, time_sync…) sont générés par la plateforme et peuvent apparaître dans l'historique d'une balise ou dans vos webhooks, sans pouvoir être créés depuis l'API.
États d'une commande
status | Signification |
|---|---|
waiting_config_loaded | En attente du chargement de la configuration de la balise |
waiting | En file d'attente, pas encore transmise |
pending | Transmise à la balise, en attente d'accusé |
received | Accusé partiel reçu |
success | Exécutée avec succès |
failed | Échec après plusieurs tentatives |
canceled | Annulée avant exécution |
merged | Fusionnée avec une autre commande |
Cycle de vie typique : waiting → pending → received → success ou failed.
Trackers
Lister les balises
GET /api/v1/trackers
Paramètres : page, perPage, sort (défaut serial), order, search (filtre sur serial et alias).
Filtres additionnels — plusieurs valeurs peuvent être séparées par une virgule :
| Paramètre | Valeurs |
|---|---|
connected | true | false |
charging | true | false |
sleep | true | false |
zoneTrack | true | false |
curl "https://api.neyos-equipment.com/api/v1/trackers?perPage=10&connected=true&search=depot" \
-H "Authorization: Bearer ctk_xxxxx"
Réponse 200 — objet paginé contenant un tableau de Tracker dans data.
Récupérer une balise
GET /api/v1/trackers/:serial
Réponse 200 — un objet Tracker.
Erreur 404 — la balise n'existe pas ou n'appartient pas à votre organisation.
Modifier une balise
PATCH /api/v1/trackers/:serial
Seuls les champs alias et notes sont modifiables. Les deux sont optionnels et peuvent être remis à null.
{
"alias": "Camion 12 - dépôt nord",
"notes": "Affecté à la tournée Lyon-Grenoble"
}
Réponse 200 — la balise mise à jour.
tracker.updated.Historique des commandes d'une balise
GET /api/v1/trackers/:serial/actions
Paramètres : page, perPage, sort (défaut createdAt), order (défaut desc).
| Filtre | Valeurs (multiples séparées par ,) |
|---|---|
status | waiting, pending, received, success, failed, canceled, merged |
type | custom_commands, power_off, load_config, send_config, time_sync |
Réponse 200 — objet paginé de TrackerAction.
Commandes
Envoyer une commande à une balise
POST /api/v1/trackers/:serial/actions
| Champ | Type | Requis | Défaut |
|---|---|---|---|
type | "custom_commands" | "power_off" | oui | — |
commands | string[] | si type = custom_commands | — |
priority | number (1 à 100) | non | 50 |
{
"type": "custom_commands",
"commands": ["gnss set --rate=5000", "modem set --network_1=0"],
"priority": 50
}
{
"type": "power_off"
}
Réponse 201 — la commande a été créée et mise en file :
{
"status": "created",
"data": { }
}
Réponse 200 — la balise est déjà dans l'état demandé, aucune commande n'a été créée :
{
"status": "already_up_to_date",
"message": "Tracker is already up to date"
}
Erreurs : 404 (balise inconnue), 422 (validation).
tracker_action.updated ou en interrogeant GET /api/v1/actions/:id.Envoyer des commandes à plusieurs balises
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 }
]
}
Chaque entrée est traitée indépendamment : une erreur unitaire (balise hors organisation, commande invalide…) ne fait pas échouer les autres.
Réponse 201
{
"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": { } }
]
}
Le champ index correspond à la position de l'entrée dans le tableau envoyé, ce qui permet de rattacher chaque résultat à sa demande d'origine.
Suivre une commande
GET /api/v1/actions/:id
Réponse 200 — un TrackerAction avec sa relation attempts : chaque tentative d'envoi contient sentAt, receivedAt et response.
Annuler une commande
PUT /api/v1/actions/:id/cancel
Une commande ne peut être annulée que tant qu'elle n'a pas été transmise à la balise, c'est-à-dire au statut waiting. Une commande déjà envoyée ne peut plus être rappelée.
Réponse 200
{ "status": "canceled" }
Webhooks
Les webhooks poussent en POST les événements de votre organisation vers l'URL de votre choix. Tous les webhooks activés rattachés à votre compte reçoivent chaque événement.
Pour la mise en place côté serveur, le détail des payloads et les exemples complets, voir la page Webhook.
Lister vos webhooks
GET /api/v1/webhooks
Paramètres : page, perPage, sort (défaut createdAt), order (défaut desc), search (filtre sur url).
Récupérer un webhook
GET /api/v1/webhooks/:id
Créer un webhook
POST /api/v1/webhooks
| Champ | Type | Requis | Défaut |
|---|---|---|---|
url | string (URL valide) | oui | — |
description | string | null | non | null |
enabled | boolean | non | true |
{
"url": "https://app.mon-domaine.com/integrations/neyos",
"description": "Webhook production",
"enabled": true
}
Réponse 201 — le webhook créé, accompagné de son signingSecret :
{
"id": "end_xxx",
"url": "https://app.mon-domaine.com/integrations/neyos",
"description": "Webhook production",
"enabled": true,
"signingSecret": "whsec_2aB3cD...",
"createdAt": 1737031800000,
"updatedAt": 1737031800000
}
signingSecret n'est retourné qu'une seule fois, à la création. Il n'apparaît dans aucune autre réponse. Stockez-le immédiatement dans votre gestionnaire de secrets : en cas de perte, la seule option est de supprimer le webhook et d'en recréer un.Modifier un webhook
PUT /api/v1/webhooks/:id
Mêmes champs qu'à la création, tous optionnels : seuls les champs fournis sont modifiés. Réponse 200 — le webhook mis à jour.
Supprimer un webhook
DELETE /api/v1/webhooks/:id
Réponse 204 — pas de contenu.
Types d'événements émis
type | Émis quand… | Contenu de data |
|---|---|---|
tracker.created | Une balise est rattachée à votre organisation | Tracker |
tracker.updated | L'alias ou les notes d'une balise sont modifiés | Tracker |
tracker.deleted | Une balise est supprimée | Tracker |
tracker_action.created | Une commande est créée (via l'API ou la plateforme) | TrackerAction |
tracker_action.updated | Une commande change d'état (envoi, accusé, succès, échec…) | TrackerAction |
tracker_action.deleted | Une commande est supprimée | TrackerAction |
message.created | Une nouvelle trame est reçue d'une balise | Message |
tracker.updated n'est pas émis à chaque changement de position ou de batterie : il est volontairement limité aux modifications d'alias et de notes. Pour suivre l'activité terrain d'une balise, écoutez message.created.Chaque notification a la même enveloppe :
{
"type": "tracker.updated",
"data": { }
}
Format des dates
Le format des dates dépend de l'événement — c'est le principal piège d'intégration :
| Contexte | Format |
|---|---|
| Réponses de l'API REST | millisecondes Unix |
Événements tracker.* et message.created | ISO 8601 (2026-09-01T10:28:03.000+00:00) |
Événements tracker_action.* | millisecondes Unix |
Champ timestamp d'un élément (point, event) | secondes Unix |
Garanties de livraison
- Les webhooks désactivés (
enabled: false) ne reçoivent aucun appel. - Réponse attendue : un code
200. Toute autre réponse, ainsi qu'un timeout ou un hôte injoignable, est consignée comme un échec. - Les appels sont asynchrones, via une file de jobs : deux notifications proches dans le temps peuvent arriver dans le désordre. Fiez-vous aux horodatages du payload, pas à l'ordre de réception.
- Un même événement peut être reçu plusieurs fois : utilisez l'en-tête
X-Neyos-Event-Idcomme clé d'idempotence. - Chaque notification est tracée côté Neyos (URL, corps envoyé, code HTTP, temps de réponse, statut), et le champ
sentAtdu webhook est mis à jour à chaque envoi.
Signature des notifications
Chaque appel webhook sortant est signé en HMAC-SHA256 à l'aide du signingSecret retourné à la création du webhook, et accompagné des en-têtes X-Neyos-Timestamp, X-Neyos-Signature et X-Neyos-Event-Id.
Codes d'erreur
| Code | Cas typiques |
|---|---|
200 | Succès |
201 | Ressource créée |
204 | Succès sans contenu (suppression) |
401 | Jeton manquant, invalide, expiré ou révoqué |
403 | Action interdite |
404 | Ressource introuvable ou appartenant à une autre organisation |
422 | Erreur de validation (type invalide, url mal formée, commands vide…) |
500 | Erreur interne |
Les erreurs de validation 422 détaillent les champs en faute :
{
"errors": [
{ "message": "The url field must be a valid URL", "rule": "url", "field": "url" }
]
}