Passer au contenu principal

Événements

POST /v1/events — événements génériques trackés par le marchand (vues de page, leads, analytics custom). Même schéma HMAC que les inscriptions, sans dédup email/phone.

Écrit par Support

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 (une adresse email), utilisez plutôt /v1/signups : chaque adresse email n'y est comptée qu'une fois par boutique. Les numéros de téléphone n'y sont pas dédupliqués. /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 juste après en avoir créé une pour la faire activer.

Révoquer une clé publique ne l'arrête pas à lui seul : les appels signés continuent d'être acceptés jusqu'à ce que le support la désactive. Prévenez le support chaque fois que vous révoquez une clé publique.

Corps

{
  "name":       "lead_submitted",
  "properties": { "plan": "pro", "country": "DZ", "form": "footer" },
  "nonce":      "32-hex-single-use"
}

Champ

Type

Requis

Notes

name

string ≤ 64 octets

✅

Nom d'événement. snake_case recommandé. La limite compte des octets : une lettre arabe en vaut deux. Un nom absent, vide ou plus long n'est pas signalé : l'appel renvoie quand même 202 et l'événement est jeté.

properties

object

Valeurs sérialisables JSON. Stockées telles quelles.

nonce

32-hex string

✅

Utilisez la même valeur que l'en-tête X-DZ-Nonce (un corps sans nonce reçoit la valeur de l'en-tête). 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 stocké avec chaque événement, mais aucun endpoint de l'API ni aucun écran du dashboard ne liste les événements stockés : ce que vous pouvez relire, avec une clé plateforme, c'est le compteur mensuel de GET /v1/usage (usage.event.total). Restez quand même sur un vocabulaire petit et stable, et é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 202 puis 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 (l'API n'accepte pas de batch). Chaque appel compte dans la limite par minute de la boutique, partagée par toutes ses clés.

Erreurs

Mêmes que /v1/signups. Voir Erreurs. Les trois qui piègent le plus sur cet endpoint :

HTTP

Code / Message

Cause

400

bad_request "Idempotency-Key header is required for write requests"

En-tête manquant

400

bad_request "Idempotency-Key must be <=64 chars, [A-Za-z0-9_-:.]"

Trop long, ou utilise des caractères hors de cet ensemble (les +, /, = du base64 sont rejetés)

403

forbidden "API is in pilot mode; key not enrolled"

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.created en API v1 ; seules les commandes créées via POST /v1/orders le 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.

Avez-vous trouvé la réponse à votre question ?