Tracker d'événements généraliste. Utilisez-le pour tout ce que vous voulez analyser et qui n'est pas une inscription :
Vues de page
Soumissions de formulaires lead
Click-tracking sur landing pages
Événements custom définis par le marchand
Si vos données ont une identité utilisateur significative (email/phone), utilisez plutôt /v1/signups — vous obtenez la dédup par utilisateur. /v1/events est pour le volume élevé sans identité.
Auth
Clé publique + HMAC. Même schéma que /v1/signups. Votre backend signe chaque appel.
⚠️ Attention — Deux choses qui bloquent une clé toute neuve
Barrière pilote. L'API est réservée au pilote en production. Une clé que DZBuild n'a pas inscrite renvoie
403 forbidden"API is in pilot mode; key not enrolled"à chaque appel.Délai d'activation. Une clé publique fraîchement émise n'est pas utilisable à l'instant où elle est créée. Tant qu'elle n'est pas activée pour ces endpoints, vous obtenez
401 unauthorized"Invalid or revoked public key". Contactez le support si une nouvelle clé est encore rejetée après une courte attente.
La révocation n'est pas instantanée non plus : après révocation d'une clé publique, des appels peuvent encore être acceptés pendant un court moment. S'il vous faut arrêter une clé immédiatement, demandez au support.
Corps
{
"name": "lead_submitted",
"properties": { "plan": "pro", "country": "DZ", "form": "footer" },
"nonce": "32-hex-single-use"
}
Champ | Type | Requis | Notes |
| string ≤ 64 | ✅ | Nom d'événement. |
| object | Valeurs sérialisables JSON. Stockées telles quelles. | |
| 32-hex string | ✅ | Usage unique, pour toujours. Voir Dédup — la fenêtre d'1 heure n'est que le garde-fou externe ; un nonce n'est jamais utilisable deux fois. |
Les requêtes POST doivent aussi porter un en-tête Idempotency-Key (≤ 64 caractères, charset [A-Za-z0-9_-:.]). Sans lui, vous obtenez 400 bad_request et l'événement n'est jamais mis en file. Le nonce de 32 caractères hex que vous générez déjà est une valeur valide — réutilisez-le.
name est ce sur quoi vous filtrerez ensuite : restez sur un vocabulaire petit et stable — évitez de générer les noms dynamiquement (ex. viewed_product_42 est mauvais ; utilisez name="viewed_product" avec properties.product_id=42).
Réponse 202
{
"data": { "status": "queued", "kind": "event", "store_id": 13 },
"meta": { "request_id": "...", "api_version": "v1", "edge": true }
}
Même flow que les signups : accepté en ~30 ms, stocké sous environ 5 s.
Dédup
La dédup porte sur le nonce seul, par boutique. Pas de dédup par email.
Un doublon est purement et simplement jeté : rien n'est stocké, aucun compteur de consommation ne bouge, et rien dans l'API ne vous le signale. L'appel a quand même renvoyé 202, parce que la dédup arrive après l'acceptation. Le doublon vous est donc invisible — générez toujours un nonce frais.
Le nonce est gardé en deux temps, avec des durées de vie différentes :
Pendant 1 heure, un nonce réutilisé est rejeté d'emblée avec
401 unauthorized"Nonce reused".Pour toujours ensuite, un nonce recyclé est accepté avec
202puis silencieusement écarté — pas d'erreur, et pas d'événement.
Exemple : tracking de vues de page (Node.js, server-side)
import crypto from 'node:crypto';export async function trackEvent(name, properties = {}) {
const KEY_ID = process.env.DZ_PUBLIC_KEY;
const SECRET = process.env.DZ_SIGNING_SECRET;
const nonce = crypto.randomBytes(16).toString('hex');
const ts = Math.floor(Date.now() / 1000).toString();
const body = JSON.stringify({ name, properties, nonce });
const hash = crypto.createHash('sha256').update(body).digest('hex');
const sig = crypto.createHmac('sha256', SECRET).update(`${KEY_ID}\n${nonce}\n${ts}\n${hash}`).digest('hex'); await fetch('https://api.dzbuild.app/v1/events', {
method: 'POST',
headers: {
'Authorization': `DZ-Public ${KEY_ID}`,
'X-DZ-Timestamp': ts, 'X-DZ-Nonce': nonce, 'X-DZ-Signature': sig,
'Idempotency-Key': nonce, // obligatoire sur chaque POST
'Content-Type': 'application/json',
},
body,
});
}// Dans un middleware Express :
app.use((req, res, next) => {
trackEvent('page_view', { path: req.path, ua: req.get('user-agent') }).catch(() => {});
next();
});
Notez qu'on n'attend pas l'appel depuis le middleware page-view — fire-and-forget pour ne pas bloquer la requête utilisateur. L'API répond en ~30 ms de toute façon, mais ça protège contre les soucis réseau transitoires.
Ce qui compte dans votre quota
Chaque appel /v1/events qui aboutit réellement incrémente usage.event.total ET usage.event.billable. Pas de tier « lectures gratuites puis écritures facturables » ici — les events sont facturables dès la requête 1. Les doublons (même nonce) ne bougent ni l'un ni l'autre, puisqu'ils ne sont jamais stockés.
Si le volume monte, batchez côté vous : stockez dans votre propre queue et tirez un appel /v1/events par event logique en lots de 1 (pas de batch en v1 ; feature v1.1 pour la vraie télémétrie haut volume).
Erreurs
Mêmes que /v1/signups. Voir Erreurs. Les trois qui piègent le plus sur cet endpoint :
HTTP | Code / Message | Cause |
400 |
| En-tête manquant |
400 |
| Trop long, ou utilise des caractères hors de cet ensemble (les |
403 |
| Clé non inscrite au pilote |
Quand ne pas utiliser /v1/events
Pour les commandes vitrine — le dashboard du marchand les enregistre déjà, et les dupliquer ici ne fait que gonfler votre compteur d'events. Notez que les commandes vitrine ne déclenchent pas de webhook
order.createden API v1 ; seules les commandes créées viaPOST /v1/ordersle font (voir le Catalogue d'événements).Pour les événements server-internes non liés aux données marchand (CPU, hits cache). Utilisez un vrai APM.
Pour les volumes massifs (plus d'1M d'events/jour). Construisez votre pipeline analytique et exportez seulement les agrégats ici.