API Ask
La validation humaine en un seul appel HTTP. Votre script ou job CI POSTe une question avec quelques actions possibles. Zenhook notifie un humain (push, email, desktop) et l'appel HTTP retourne ce qu'il a choisi. Pas de SDK, pas de session, pas de framework de polling.
Poser une question
Même token que l'URL webhook de votre canal : un ask est simplement un événement en forme de question sur le canal. Par défaut, l'appel bloque jusqu'à la réponse d'un humain (ou ~80 secondes, voirmodes d'attente).
curl -X POST https://zenhook.dev/api/ask/abc123def456 \
-H "Content-Type: application/json" \
-d '{
"title": "Déployer api-server en production ?",
"message": "3 commits depuis le dernier déploiement. Tests verts.",
"actions": ["Déployer", "Annuler"],
"default": "Annuler",
"timeout": 600
}'{
"id": "ask_cmr5o5l6",
"status": "answered",
"answer": "Déployer",
"answeredVia": "link",
"answeredAt": "2026-07-04T09:41:12.000Z",
"actions": ["Déployer", "Annuler"],
"defaultAction": "Annuler",
"askUrl": "https://zenhook.dev/ask/…",
"pollUrl": "https://zenhook.dev/api/ask/…/ask_cmr5o5l6"
}Tout le canal reçoit la question comme une alerte normale, avec un lien Répondre. Le lien ouvre une page de réponse publique. Un tap sur le téléphone et l'appel bloqué ci-dessus retourne. Quiconque détient le lien peut répondre ; aucun compte Zenhook requis.
Champs de la requête
Modes d'attente
Une requête HTTP retenue est plafonnée autour de 80 secondes (limites proxy). Pour les décisions plus longues, bouclez surpollUrl : chaque poll peut lui-même attendre avec ?wait=60, la boucle est donc économe :
RES=$(curl -s -X POST "https://zenhook.dev/api/ask/$TOKEN" \
-H 'Content-Type: application/json' \
-d '{"title":"Déployer en prod ?","actions":["Déployer","Annuler"],"timeout":600}')
while [ "$(echo "$RES" | jq -r .status)" = "pending" ]; do
RES=$(curl -s "$(echo "$RES" | jq -r .pollUrl)?wait=60")
done
if [ "$(echo "$RES" | jq -r .answer)" = "Déployer" ]; then
./deploy.sh
else
echo "Bloqué par un humain." && exit 1
fiOu n'attendez pas du tout et recevez le résultat en push :
{
"title": "Rembourser 420 $ au client #1847 ?",
"actions": ["Rembourser", "Escalader", "Ignorer"],
"timeout": 3600,
"wait": false,
"callbackUrl": "https://votre-app.com/hooks/zenhook-answer"
}Sémantique des réponses
- La première réponse gagne.Deux personnes qui tapent en même temps ne peuvent pas gagner toutes les deux ; le perdant voit qui a répondu en premier.
- L'expiration n'invente jamais de réponse.Un ask expiré a
status: "expired"etanswer: null. Votredefaultrevient commedefaultAction; l'appliquer reste votre décision. - Les réponses sont auditées.Qui a répondu (si connecté), par quelle surface, et quand.
Limites par plan
Free inclut 25 asks par mois par workspace. Pro monte à 1 000 asks par mois. Les asks comptent aussi dans votre quota mensuel d'événements.