API Capture
Tout entre dans Kilden par un seul endpoint :
POST https://ingest.kilden.io/captureContent-Type: application/jsonLes SDK l’utilisent sous le capot ; vous pouvez l’appeler directement depuis n’importe quel backend, script ou intégration. Il n’existe aucun autre chemin d’écriture.
Le corps est toujours un batch — un événement seul est un batch de un :
{ "write_key": "YOUR_WRITE_KEY", "sent_at": "2026-07-11T12:00:00.000Z", "batch": [ { "uuid": "0197f9d2-5e5a-7cc3-b1a4-1f0e9a2b3c4d", "event": "order_completed", "distinct_id": "user_4821", "properties": { "total": 49.9, "currency": "EUR" }, "timestamp": "2026-07-11T11:59:58.000Z" } ]}| Champ | Requis | Notes |
|---|---|---|
write_key |
oui | Clé publique ou secrète, dans le corps (pas un header). Les clés secrètes marquent les événements comme des faits côté serveur — voir Niveaux de confiance |
sent_at |
non | Quand le client a envoyé la requête. Sert uniquement à corriger la dérive d’horloge du client : real_time ≈ timestamp + (server_now − sent_at) |
batch |
oui | 1 à 1000 événements |
identity_token |
non | Emplacement de repli pour le JWT de vérification d’identité quand un header est impossible (sendBeacon). Le header Authorization gagne si les deux sont présents |
Par événement :
| Champ | Requis | Notes |
|---|---|---|
uuid |
oui | Un UUID valide, généré par le client. Utilisez UUID v7. C’est la clé d’idempotence : les réessais avec le même uuid sont dédupliqués, donc réessayer sur n’importe quel échec est toujours sûr |
event |
oui | Nom de l’événement, ≤ 200 caractères. Les noms préfixés par $ sont réservés au système |
distinct_id |
oui | ≤ 512 caractères. UUID v7 préfixé par anon_ = anonyme ; tout le reste est traité comme un id d’utilisateur identifié |
properties |
non | N’importe quel objet JSON. Jamais validé par schéma — l’enveloppe est typée, le payload est à vous |
timestamp |
non | ISO 8601. Par défaut, l’heure de réception serveur ; corrigé avec sent_at quand les deux sont présents |
Headers :
Authorization: Bearer <jwt>— token de vérification d’identité pour tout le batch (un batch appartient à une seule session de navigateur). Max 4096 octets.Content-Encoding: gzip— accepté et recommandé pour les gros batchs.
Limites : corps de requête ≤ 5 MiB, batch ≤ 1000 événements.
200 dès que le batch est validé et mis en file (capture ne bloque jamais sur le traitement en aval) :
{ "status": "ok" }Les erreurs sont en texte brut, pas en JSON :
| Statut | Signification |
|---|---|
400 |
Requête malformée : invalid JSON body: …, invalid gzip body, write_key is required, batch must not be empty, batch exceeds 1000 events, batch[i]: uuid is not a valid UUID, batch[i]: event is required, batch[i]: event exceeds 200 chars, batch[i]: distinct_id is required, batch[i]: distinct_id exceeds 512 chars, batch[i]: properties is not valid JSON, identity token too large |
401 |
unknown write_key |
403 |
origin not allowed for this project — voir origines autorisées |
405 |
Méthode autre que POST/OPTIONS |
Un échec de validation rejette le batch entier — corrigez et réessayez (les UUID rendent cela sûr).
Exemple côté serveur
Section intitulée « Exemple côté serveur »curl -X POST https://ingest.kilden.io/capture \ -H 'Content-Type: application/json' \ -d '{ "write_key": "sk_your_secret_key", "sent_at": "2026-07-11T12:00:00Z", "batch": [{ "uuid": "0197f9d2-5e5a-7cc3-b1a4-1f0e9a2b3c4d", "event": "subscription_renewed", "distinct_id": "user_4821", "properties": {"plan": "pro", "mrr": 49}, "timestamp": "2026-07-11T12:00:00Z" }] }'Les événements envoyés avec une clé secrète sont marqués source=server et verified=true — la clé secrète est l’authentification. N’embarquez jamais une clé secrète dans un navigateur ou une application mobile ; c’est à ça que servent les clés publiques.
/capture est un endpoint d’écriture public, ouvert en CORS par conception :
- Chaque réponse porte
Access-Control-Allow-Origin: *(sans credentials). - Le preflight
OPTIONSrépond204avecAccess-Control-Allow-Methods: POST,Access-Control-Allow-Headers: Content-Type, Authorization, Content-Encoding,Access-Control-Max-Age: 86400.
Origines autorisées
Section intitulée « Origines autorisées »Une write key publique est visible dans le source de votre page, donc n’importe qui pourrait la copier. Pour empêcher d’autres sites de polluer vos données, configurez des origines autorisées dans les réglages du projet : quand la liste est non vide, les requêtes navigateur dont l’Origin ne correspond pas reçoivent 403.
- Motifs :
scheme://host[:port], avec wildcards de sous-domaine (https://*.example.com— ne couvre pas l’apex ; listez les deux si nécessaire). - Liste vide (défaut) = tout autoriser.
- Les requêtes sans header
Origin(curl, backends, applis mobiles) passent toujours — ce vecteur est couvert par les clés secrètes et la vérification d’identité, pas par le filtrage d’Origin. C’est une réduction de bruit contre la réutilisation réelle de clés dans les navigateurs, pas une frontière de sécurité.