Fonctionnalités
Alertes d’attente
Waity appelle votre webhook quand l’attente en direct d’un lieu passe sous votre seuil, pour qu’un agent n’ait pas à redemander sans cesse. Tous les forfaits en ont, Free compris.
Fonctionnement
Créez une alerte pour un lieu avec un seuil en minutes et un webhook https. Après chaque minute d’ingestion, Waity vérifie les lieux qui viennent de recevoir de nouvelles mesures et envoie en POST un corps JSON signé à votre webhook quand l’attente est au seuil ou en dessous.
Une alerte lit la même réponse en direct que GET /v1/places/{id}, elle ne contredit donc jamais l’API. Elle se déclenche seulement quand now.usable vaut true, que l’unité est la minute et que now.value vaut au plus under. Une borne inférieure (« plus de 60 »), un nombre périmé ou en pause, un lieu fermé ou l’absence de données ne la déclenchent jamais.
Créer une alerte
POST /v1/alerts avec une clé d’API et un corps JSON. La réponse est l’alerte, avec son id et le secret de signature. Le secret n’est affiché qu’une fois : conservez-le là où votre webhook peut le lire.
| Champ | Ce qu’il accepte |
|---|---|
place_id | Un lieu, une file ou un service. Un aéroport, un poste frontière ou un campus hospitalier n’a pas d’attente unique, donc son id est refusé, avec les id de ses files ou services. |
under | Des minutes entières, de 1 à 600. |
webhook_url | L’adresse où Waity envoie le POST. https uniquement ; voir les règles ci-dessous. |
repeat | false (par défaut) se déclenche une fois, puis l’alerte passe à fired. true se déclenche à nouveau après que l’attente est remontée au-dessus du seuil plus 5 minutes, au plus une fois toutes les 30 minutes. |
expires_at | Facultatif, ISO 8601. Par défaut, 24 heures à partir de maintenant ; au plus 30 jours. |
curl -X POST "https://api.waity.ai/v1/alerts" \
-H "X-Api-Key: $WAITY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"place_id":"pl_nvk0wkb3ps","under":30,"webhook_url":"https://example.com/waity/webhook"}'
201Réponse
{
"id": "al_3k9qx2m7t4p8w1za",
"place": {
"id": "pl_nvk0wkb3ps",
"name": "Ysleta Passenger Vehicles, Standard",
"category": "border"
},
"under": 30,
"unit": "min",
"repeat": false,
"webhook_url": "https://example.com/waity/webhook",
"status": "armed",
"created_at": "2026-10-31T19:02:11Z",
"expires_at": "2026-11-01T19:02:11Z",
Règles de l’URL du webhook
Pour que les alertes n’atteignent pas des réseaux privés, Waity refuse une URL de webhook qui :
- n’utilise pas https sur le port par défaut (443), ou contient un nom d’utilisateur ou un mot de passe ;
- utilise une adresse IP au lieu d’un nom d’hôte, si bien que les adresses privées, de loopback, link-local et de métadonnées cloud sont toutes refusées ;
- utilise localhost, un nom à un seul libellé, ou un nom privé ou réservé comme .local, .internal, .lan ou .home.arpa ;
- pointe vers Waity lui-même.
Waity ne résout aucun nom lui-même et ne suit jamais une redirection : une réponse 3xx compte comme une livraison échouée.
Lister, lire et supprimer
GET /v1/alerts renvoie vos alertes, des plus récentes aux plus anciennes, avec leur statut et leur dernière livraison. Les clés d’un compte partagent une liste ; une clé sans compte a la sienne. GET /v1/alerts/{id} en lit une, et DELETE /v1/alerts/{id} la supprime et arrête ses livraisons.
curl
curl "https://api.waity.ai/v1/alerts" \
-H "X-Api-Key: $WAITY_API_KEY"
curl -X DELETE "https://api.waity.ai/v1/alerts/al_3k9qx2m7t4p8w1za" \
-H "X-Api-Key: $WAITY_API_KEY"
| Statut | Ce qu’il accepte |
|---|---|
armed | Attend que l’attente passe sous le seuil. |
fired | Une alerte unique qui s’est déclenchée. |
expired | Son expires_at est passé sans déclenchement. |
failing | La dernière tentative de livraison a échoué ; voir last_delivery. De nouvelles tentatives suivent tant qu’il en reste. |
disabled | 20 tentatives de livraison échouées d’affilée. Créez une nouvelle alerte une fois votre webhook opérationnel. |
Le webhook
Chaque livraison est un POST avec un corps JSON. Lisez d’abord warnings à l’utilisateur, puis summary. now.value reste valable jusqu’à now.usable_until ; ensuite, interrogez de nouveau GET /v1/places/{id}.
POST
{
"type": "wait.under",
"alert": {
"id": "al_3k9qx2m7t4p8w1za",
"under": 30
},
"place": {
"id": "pl_nvk0wkb3ps",
"name": "Ysleta Passenger Vehicles, Standard",
"category": "border",
"url": "https://waity.ai/places/ysleta-passenger-vehicles-standard-kb3ps"
},
"now": {
"value": 25,
"unit": "min",
"measured_at": "2026-10-31T13:58:00-06:00",
"usable_until": "2026-10-31T15:28:00-06:00",
"basis": "estimate"
},
"summary": "About 25 min to enter the US, estimated by the border agency, updated 2 min ago.",
"warnings": [],
"links": {
"place": "https://api.waity.ai/v1/places/pl_nvk0wkb3ps",
"page": "https://waity.ai/places/ysleta-passenger-vehicles-standard-kb3ps",
"alert": "https://api.waity.ai/v1/alerts/al_3k9qx2m7t4p8w1za",
"docs": "https://waity.ai/docs/alerts"
}
}
Chaque requête porte ces en-têtes :
Waity-Signature: t=<unix>,v1=<hex>:test l’heure de la signature, en secondes unix ;v1est le HMAC-SHA256 de la chaîne formée det, d’un point et du corps brut, avec le secret complet de l’alerte comme clé.Waity-Alert: l’id de l’alerte.Waity-Delivery: l’id de la livraison, le même à chaque nouvelle tentative, pour que vous puissiez écarter les doublons.
Vérifier la signature
Vérifiez la signature sur les octets bruts avant d’analyser le JSON, comparez en temps constant et rejetez un t vieux de plus de 5 minutes.
import crypto from "node:crypto";
import express from "express";
const app = express();
const secret = process.env.WAITY_ALERT_SECRET; // whsec_…
// The raw body: the signature covers the exact bytes Waity sent.
app.post("/waity/webhook", express.raw({ type: "application/json" }), (req, res) => {
const parts = Object.fromEntries(
(req.get("Waity-Signature") ?? "").split(",").map((p) => p.split("=", 2)),
);
const expected = crypto
.createHmac("sha256", secret)
.update(`${parts.t}.${req.body}`)
.digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) <= 300;
const ok =
fresh &&
typeof parts.v1 === "string" &&
parts.v1.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
if (!ok) return res.status(400).end();
const event = JSON.parse(req.body);
// Read event.warnings first, then event.summary.
res.status(204).end();
});
app.listen(3000);
Nouvelles tentatives
Répondez par n’importe quel 2xx sous 10 secondes. Toute autre réponse est une tentative échouée, retentée environ 1, 5, 25 minutes plus tard. Après 20 tentatives échouées d’affilée, l’alerte est désactivée.
Limites par forfait
Chaque forfait permet un certain nombre d’alertes actives à la fois. Une de plus reçoit 409 alert_limit avec un message indiquant la limite de votre forfait. Chaque requête sur les alertes compte comme un appel ; les livraisons ne comptent jamais. Une clé sans compte compte comme Free.
| Forfait | Alertes actives |
|---|---|
| Free | 1 |
| Plus | 10 |
| Pro | 100 |
| Team | 1 000 |
Urgences et soins urgents
Pour les alertes d’urgences et de soins urgents, warnings[0] de chaque livraison est la ligne 911, dite une fois, comme dans chaque réponse pour les urgences.
Voir aussi
Ensuite indique quand une attente devrait baisser, d’après l’historique. Lire une réponse explique chaque champ, et chaque champ figure dans la Référence de l’API.