Documentation API
Intégrez LogsNinja à votre application en quelques minutes. Envoyez des événements depuis n'importe quel langage avec une simple requête HTTP POST.
Démarrage rapide
Obtenir le prompt de démarrageAuthentification
Toutes les requêtes doivent inclure un token API dans le header Authorization.
Authorization: Bearer YOUR_API_TOKEN
Vous pouvez créer des tokens API depuis les paramètres de votre projet. Accéder aux tokens
Si vous êtes un agent IA plutôt qu'un humain, vous pouvez obtenir un token sans qu'on vous le copie-colle. Voir l'autorisation de l'appareil
Limites de débit & quotas
Les limites dépendent de votre plan. La limite de débit s'applique à l'organisation et est partagée entre tous les tokens API ; créer des tokens supplémentaires ne l'augmente pas.
La limite globale par organisation s'applique à chaque endpoint authentifié par un token API, y compris POST /v1/events, PUT /v1/users, POST /v1/ping, PUT /v1/metrics, /v1/org/charts, /v1/org/widgets, et les opérations de suppression. Chaque appel consomme une requête de cette même limite partagée.
/v1/device/authorize (pas encore de token à ce stade) est limité à 10 requêtes par heure et par adresse IP, et /v1/device/token à 60 requêtes par 5 minutes et par adresse IP.
| Plan | Limite d'appels | Événements / mois | Images / mois | Images par événement |
|---|---|---|---|---|
| Free | 60 req/min | 3,000 | – | Non inclus |
| Starter | 300 req/min | 100,000 | 20,000 | 1 par événement · 1 Mo max · redimensionnée à 1024px · corps de requête jusqu'à 1 Mo |
| Plus | 1,200 req/min | 500,000 | 100,000 | 4 par événement · 1 Mo max · redimensionnée à 1024px · corps de requête jusqu'à 8 Mo |
| Enterprise | Sur mesure | Sur mesure | Sur mesure | Sur mesure |
Lorsque la limite de débit est dépassée, l'API renvoie 429 avec Too many requests. Le nombre d'événements et le nombre d'images ont chacun leur propre quota mensuel ; lorsque l'un des deux est atteint, l'API renvoie 429 avec Monthly event or hosted image quota exceeded. Upgrade your plan to continue.
En-têtes de quota
Chaque réponse réussie de POST /v1/events inclut les en-têtes suivants :
X-Quota-Remaining: 2497
X-Image-Quota-Remaining: 18320
X-Plan: starter
X-Quota-Remaining– événements restants pour le mois calendaire en cours.-1signifie qu'ils sont illimités (Enterprise).X-Image-Quota-Remaining– images restantes pour le mois calendaire en cours.-1signifie illimité (Enterprise).X-Plan– le plan actuel de l'organisation (free,starter,plus,enterprise).
Format des métadonnées
Le champ metadata sur les événements et les utilisateurs suit les mêmes règles :
- Clés : lettres minuscules, chiffres, tirets et underscores uniquement (
^[a-z0-9_-]+$) - Valeurs :
string,number, ouboolean - Maximum 20 clés par objet
- Clés : 100 caractères max
- Valeurs texte : 255 caractères max
{
"plan": "pro",
"amount": 49,
"score": 4.8,
"is-trial": false
}
Prompt de démarrage
Collez ce prompt dans Claude Code, Cursor, Codex ou tout autre agent IA pour démarrer immédiatement.
You are integrating LogsNinja into this project.
LogsNinja is a real-time event tracking and push notification platform. Use its REST API to log application events, track users, update dashboard metrics, and trigger instant push notifications to mobile and desktop devices.
LogsNinja provides no SDK – all integration is done via plain HTTP calls using the libraries and conventions already present in this project.
## Fetch the full API documentation
Before writing any integration code, fetch the complete reference in Markdown:
curl https://logsninja.com/fr/docs -H "Accept: text/markdown"
Read it carefully – it covers all endpoints, request fields, response codes, rate limits, and examples.
## Core concepts
**Events** – send a POST to /v1/events. All fields are covered in the documentation.
**Streams** – lightweight channels grouping events. Auto-created on first use (e.g. "payments", "errors").
**Users** – PUT /v1/users to create or update a user profile. The same id is used in the user field when sending events. Optional country_code is caller-supplied (LogsNinja does not geolocate IPs itself) – see the full docs for how to obtain it.
**Metrics** – PUT /v1/metrics to create or update a numeric, text, currency, or percent dashboard tile. Supports atomic diff increments.
**Presence** – POST /v1/ping to signal a user is online without creating an event.
**Event chains** – link events sequentially with before/after fields to trace multi-step workflows.
**Charts** – POST/GET/PATCH/DELETE /v1/org/charts to manage dashboard charts. Same fields and validation rules as the dashboard's own chart editor.
**Widgets** – POST/GET/PATCH/DELETE /v1/org/widgets (plus POST /v1/org/widgets/reorder) to manage what's on the dashboard. The dashboard is a masonry layout, not a rigid grid: "small" widgets (metric, online_users) are meant for width 1 or 2 and render at exactly half the visual height of "large" widgets (chart, world_map, events_7d, top_countries), meant for width 2 or 3 (full row) – keep that in mind when arranging one via the API.
## Authentication
All requests require:
Authorization: Bearer YOUR_API_TOKEN
Creating an account and generating a token both require a human to sign in
to the LogsNinja dashboard - you cannot do either yourself. If you don't
already have a token (e.g. in an environment variable), stop and ask the
person you're working with to create one at https://logsninja.com/fr/my/tokens
and give it to you (for example as a LOGSNINJA_API_TOKEN environment
variable) before you continue.
## API base URL
https://api.logsninja.com/v1
## MCP server
If you are an AI agent with MCP support rather than a code-generation assistant, LogsNinja is also usable directly as an MCP server at https://logsninja.com/mcp (same Bearer token as above) – it exposes tools to manage charts and dashboard widgets, explore project data, and create/delete test events, users, and metrics, without writing HTTP calls yourself. See the full docs for the tool list.
## Integration guidelines
- Use the HTTP client and patterns already established in this project – do not introduce new dependencies.
- All LogsNinja calls must be fire-and-forget from the application's perspective: they must never block the main flow or surface errors to the end user.
- Apply a 3-second timeout to every HTTP call, if possible.
- If this project already has a job queue, background worker, or retry mechanism, use it for LogsNinja calls.
- If no such mechanism exists, wrap calls in a silent try/catch (or equivalent) so that a LogsNinja failure has zero impact on the application.
## What to instrument
Scan the codebase and identify meaningful moments to send events: key user actions, business transactions, errors, background jobs, and any other signal that would be useful to monitor. For each, choose a descriptive title and a fitting emoji. Once done, provide a summary of every integration point added.
## Presence
Use presence sparingly. Sending an event with a user field already updates that user's online status for 15 minutes, so a separate ping is redundant in those cases. Only call POST /v1/ping when you know the user is active but no event will be sent soon – for example on login, or during an idle session. Do not ping on every page view or API call.
Envoyer un événement
https://api.logsninja.com/v1/events
En-têtes
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
Corps de la requête
{
"project": "YOUR_PROJECT_ID",
"stream": "payments",
"title": "New subscription",
"content": "[email protected] subscribed to Pro",
"emoji": "💳",
"metadata": { "plan": "pro", "amount": 49 },
"notify": true
}
Exemples
curl -X POST https://api.logsninja.com/v1/events \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"project": "YOUR_PROJECT_ID",
"stream": "payments",
"title": "New subscription",
"content": "[email protected] subscribed to Pro",
"notify": true
}'
await fetch('https://api.logsninja.com/v1/events', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
project: 'YOUR_PROJECT_ID',
stream: 'payments',
title: 'New subscription',
content: '[email protected] subscribed to Pro',
notify: true,
}),
});
import requests
requests.post(
'https://api.logsninja.com/v1/events',
headers={
'Authorization': 'Bearer YOUR_API_TOKEN',
'Content-Type': 'application/json',
},
json={
'project': 'YOUR_PROJECT_ID',
'stream': 'payments',
'title': 'New subscription',
'content': '[email protected] subscribed to Pro',
'notify': True,
},
)
Champs de l'événement
| Champ | Type | Requis | Description |
|---|---|---|---|
project |
string | ✓ | Identifiant du projet. Retrouvez-le dans les paramètres du projet. |
stream |
string | ✓ | Le stream auquel appartient cet événement. Créé automatiquement à la première utilisation. |
title |
string | ✓ | Titre court de l'événement. 100 caractères maximum. |
content |
string | Détails complémentaires, 500 caractères maximum. Markdown pris en charge : gras, italique, code, listes et liens. | |
emoji |
string | Emoji pour identifier visuellement lévénement. Par défaut 🔔 si omis. Formats acceptés : caractère emoji ("💳"), shortcode (":credit_card:"), ou code hexadécimal ("1F4B3"). Aussi utilisé comme image de notification push. Parcourir les emojis disponibles. |
|
metadata |
object | Métadonnées clé/valeur. Voir les règles de format ci-dessus. | |
user |
string | L'identifiant de votre utilisateur dans votre application (le même id que celui transmis à PUT /v1/users). L'utilisateur n'a pas besoin d'exister : les événements sont liés automatiquement à sa création. Envoyer un événement en temps réel avec le champ user compte aussi comme présence : l'utilisateur est considéré en ligne pendant 15 minutes après son dernier événement lié ou ping. Les événements backdatés avec timestamp n'affectent pas la présence. |
|
images |
string[] | Images pour cet événement. Nécessite un plan payant. Soit un tableau d'URLs d'images HTTPS publiques à récupérer et stocker (les doublons au sein d'un même événement sont dédupliqués), soit les fichiers eux-mêmes envoyés en multipart/form-data. Les images sont traitées de manière asynchrone et conservées 30 jours. Voir Envoi d'images pour le contrat complet, les limites de taille, les formats acceptés, les prérequis des URLs et comment lire images_status. |
|
notify |
boolean | Envoyer une notification push aux appareils abonnés. Par défaut : false. Ne peut pas être true si timestamp est défini. Lorsque notify est présent, la réponse contient aussi notification_queued ; false signifie que l’événement a été enregistré mais que la file de notifications mobiles restait indisponible après une nouvelle tentative. | |
timestamp |
integer | Timestamp Unix (en secondes) pour antidater l'événement. Doit être dans le passé. Ne peut pas être combiné avec notify: true. Les événements backdatés n'affectent pas la présence en ligne. | |
before |
string | L'évènement sera placé avant celui dont l'ID aura été transmis dans cette propriété, dans une chaîne d'événements. | |
after |
string | L'évènement sera placé après celui dont l'ID aura été transmis dans cette propriété, dans une chaîne d'événements. |
Envoi d'images
Il y a deux façons d'attacher des images à un événement, toutes deux réservées aux plans payants et traitées de la même manière, de façon asynchrone : passer un tableau d'URLs HTTPS publiques dans le champ JSON images pour que LogsNinja les récupère et les stocke, ou envoyer les fichiers eux-mêmes dans la même requête POST /v1/events en multipart/form-data.
Envoi binaire (multipart/form-data)
La requête comporte une partie event et une ou plusieurs parties fichier nommées image :
| Partie | Description |
|---|---|
event |
Une chaîne contenant le corps JSON exact que vous enverriez sinon en application/json : project, stream, title et tout autre champ, avec metadata comme véritable objet JSON (pas des champs de formulaire metadata[key]). Elle peut toujours inclure un tableau images d'URLs, stockées en plus des fichiers envoyés. |
image |
Une partie par fichier, chacune envoyée en tant que fichier (avec un nom de fichier) et portant un Content-Type image/jpeg, image/png ou image/webp. Les parties portant tout autre nom, et les parties image qui ne sont pas des fichiers, sont ignorées. |
curl -X POST https://api.logsninja.com/v1/events \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-F 'event={"project":"YOUR_PROJECT_ID","stream":"payments","title":"New subscription","metadata":{"plan":"pro"},"notify":true};type=application/json' \
-F 'image=@./screenshot.png;type=image/png'
const form = new FormData();
form.append('event', JSON.stringify({
project: 'YOUR_PROJECT_ID',
stream: 'payments',
title: 'New subscription',
metadata: { plan: 'pro' },
notify: true,
}));
form.append('image', fileOrBlob, 'screenshot.png'); // Content-Type image/png
await fetch('https://api.logsninja.com/v1/events', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_TOKEN' }, // no Content-Type
body: form,
});
Erreurs synchrones
Elles sont renvoyées immédiatement dans la réponse au POST, avant la création de l'événement :
| Code | Cause |
|---|---|
400 | La partie event est absente ou n'est pas un objet JSON. |
403 | Votre plan n'inclut pas les images sur les événements. |
411 | La requête n'a pas d'en-tête Content-Length. |
413 | Un fichier dépasse la limite de taille par image de votre plan, ou le corps entier de la requête dépasse la taille maximale de votre plan. |
415 | Le Content-Type d'une partie image ne commence pas par image/. Un mauvais type d'image (p. ex. image/gif) passe ce contrôle mais échoue ensuite en bad_format. |
422 | Plus d'images que ce que votre plan autorise par événement. |
Voir Limites de débit et quotas pour le nombre d'images par plan, la taille par image et la taille maximale du corps de requête.
Récupération depuis une URL
Lorsque vous passez des URLs au lieu de fichiers, chacune doit respecter tous ces critères, sinon l'image est marquée failed :
- HTTPS uniquement, sur le port 443. Pas d'hôtes en IP littérale, pas de
localhost,.localni.internal. L'URL doit faire au plus 2048 caractères. - La réponse doit porter
Content-Type: image/jpeg,image/pngouimage/webp. Un200qui renvoie dutext/html(page d'erreur, mur de connexion) est un échec permanent – jamais réessayé. - La récupération expire après 15 secondes et suit au plus 3 redirections.
- Sur
403,404,408,425,429,500,502,503ou504, la récupération est réessayée pendant environ une minute avant que l'image soit marquéefailed. Tout autre statut échoue définitivement dès la première tentative.
Formats et traitement
- Formats acceptés : JPEG, PNG et WebP, détectés à partir des octets de signature du fichier – pas de son extension ni de son type déclaré.
- Chaque image est redimensionnée pour tenir dans la dimension maximale de votre plan et stockée à la fois en JPEG et en WebP. Les images sont conservées 30 jours.
- Un événement rétrodaté (
timestamp) dont la date est déjà hors de la fenêtre de 30 jours ignore entièrement le traitement d'images ; sonimages_statusvautexpired.
Lire le résultat
La réponse au POST inclut images_status, mais à ce moment-là il vaut toujours pending (ou none / expired) car le traitement n'a pas encore eu lieu. Il n'y a pas de webhook : relisez l'événement plus tard – avec l'outil get_event du MCP ou dans le flux d'événements du Studio – pour voir le résultat.
images_status |
Signification |
|---|---|
none | L'événement n'a pas d'images. |
pending | En file d'attente ou en cours. |
ready | Toutes les images ont été traitées. |
partial | Certaines images sont prêtes, d'autres ont échoué. |
failed | Toutes les images ont échoué. |
expired | L'événement est antérieur à la fenêtre d'images de 30 jours ; rien n'a été envoyé. |
Chaque image porte aussi une chaîne error et un error_code (too_large, bad_format ou unreachable) en cas d'échec.
Recommandation : pour un événement émis juste après la génération d'une image (un rendu, une capture, un export), envoyez le fichier plutôt qu'une URL. Une URL qui n'est pas encore accessible – ou déjà supprimée – lorsque LogsNinja la récupère fait échouer l'image, et rien ne vous prévient quand cela arrive.
Chaînes d'événements
Les champs before et after permettent de lier des événements en chaîne. Le panneau de détail affiche les événements adjacents et permet de voir la séquence complète.
Seules les références vers des événements du même projet sont résolues, et uniquement lorsque leurs dates sont cohérentes. La cible de after (prédécesseur) doit avoir une date antérieure, et la cible de before (successeur) une date postérieure.
Supprimer un événement
https://api.logsninja.com/v1/events/:id?project=YOUR_PROJECT_ID
Supprime définitivement un événement.
Créer ou mettre à jour un utilisateur
https://api.logsninja.com/v1/users
Crée ou met à jour un utilisateur applicatif. Un appel avec le même id remplace l'enregistrement.
{
"project": "YOUR_PROJECT_ID",
"id": "user_123",
"country_code": "FR",
"display_as": "[email protected]",
"metadata": { "plan": "pro", "mrr": 49 }
}
| Champ | Type | Requis | Description |
|---|---|---|---|
project |
string | ✓ | Identifiant du projet. |
id |
string | ✓ | Votre propre identifiant stable pour cet utilisateur (ex. votre ID de base de données). C'est la valeur que vous utilisez dans le champ user lors de l'envoi d'événements. |
country_code |
string | Code pays ISO 3166-1 alpha-2 (par ex. FR, US). Voir Géolocalisation pour savoir comment l'obtenir. | |
display_as |
string | Nom affiché sur le site et l'application mobile pour cet utilisateur. Si non renseigné ou null, l'id de l'utilisateur est utilisé à la place. |
|
metadata |
object | Métadonnées clé/valeur. Voir les règles de format ci-dessus. |
Exemples
curl -X PUT https://api.logsninja.com/v1/users \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"project": "YOUR_PROJECT_ID",
"id": "user_123",
"country_code": "FR",
"metadata": { "plan": "pro" }
}'
await fetch('https://api.logsninja.com/v1/users', {
method: 'PUT',
headers: {
'Authorization': 'Bearer YOUR_API_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
project: 'YOUR_PROJECT_ID',
id: 'user_123',
country_code: 'FR',
metadata: { plan: 'pro' },
}),
});
import requests
requests.put(
'https://api.logsninja.com/v1/users',
headers={
'Authorization': 'Bearer YOUR_API_TOKEN',
'Content-Type': 'application/json',
},
json={
'project': 'YOUR_PROJECT_ID',
'id': 'user_123',
'country_code': 'FR',
'metadata': {'plan': 'pro'},
},
)
Géolocalisation
LogsNinja ne détermine jamais le pays d'un utilisateur à partir de son adresse IP – country_code est entièrement fourni par l'appelant.
- Si votre backend passe par Cloudflare (Workers/Pages, ou un enregistrement DNS avec le nuage orange activé), lisez directement l'en-tête de requête
CF-IPCountry– il est déjà présent sur chaque requête entrante. - Le même principe s'applique derrière la plupart des autres CDN/réseaux de périphérie (par ex. Akamai, Bunny, Fastly, Amazon CloudFront) – ils ajoutent généralement leur propre en-tête géo équivalent. Consultez la documentation de ce fournisseur pour le nom et le format exacts de l'en-tête.
- Sinon, utilisez une bibliothèque ou un service GeoIP sur l'adresse IP de la requête (par ex. MaxMind GeoLite2, ipinfo.io, ip-api.com).
Transmettez le code obtenu en tant que country_code – il alimente le graphique de répartition par pays et le widget carte du monde.
Supprimer un utilisateur
https://api.logsninja.com/v1/users/:id?project=YOUR_PROJECT_ID
Supprime un utilisateur applicatif. Ses événements restent mais ne sont plus liés à l'utilisateur.
Signaler la présence d'un utilisateur
https://api.logsninja.com/v1/ping
Indique qu'un utilisateur est connecté, sans créer d'événement. Un utilisateur est considéré comme connecté s'il a envoyé un ping ou eu un événement lié dans les 15 dernières minutes. Si l'utilisateur n'existe pas encore, le ping est silencieusement ignoré – créez d'abord l'utilisateur via PUT /v1/users.
{
"project": "YOUR_PROJECT_ID",
"id": "user_123"
}
| Champ | Type | Requis | Description |
|---|---|---|---|
project |
string | ✓ | Identifiant du projet. |
id |
string | ✓ | L'identifiant de votre utilisateur applicatif (le même id que celui transmis à PUT /v1/users). |
Créer ou mettre à jour une métrique
https://api.logsninja.com/v1/metrics
Crée ou met à jour une métrique. Un appel avec le même id remplace la valeur. Pour les types numériques, vous pouvez aussi appliquer un delta au lieu de définir une valeur absolue.
{
"project": "YOUR_PROJECT_ID",
"id": "mrr",
"title": "MRR",
"emoji": "💰",
"value": 4900,
"value_type": "currency",
"currency": "EUR"
}
{
"project": "YOUR_PROJECT_ID",
"id": "active-users",
"title": "Active users",
"value": { "diff": 1 },
"value_type": "number"
}
| Champ | Type | Requis | Description |
|---|---|---|---|
project |
string | ✓ | Identifiant du projet. |
id |
string | ✓ | Identifiant stable de cette métrique (par ex. mrr, active-users). |
title |
string | ✓ | Libellé affiché sur la tuile métrique. |
value |
string | number | object | ✓ | La valeur de la métrique. Pour les types numériques, passez {"diff": N} pour ajouter ou soustraire N atomiquement (ex. {"diff": -1}). Non disponible pour value_type text. |
value_type |
string | ✓ | L'une de : number, text, currency, percent. |
currency |
string | Code devise ISO 4217 (par ex. EUR, USD). Requis lorsque value_type vaut currency. |
|
emoji |
string | Emoji affiché sur la tuile de métrique. Formats acceptés : caractère emoji ("💰"), shortcode (":money-bag:") ou code hexadécimal ("1F4B0"). Lorsqu’il est omis, ℹ️ est affiché par défaut sans être enregistré sur la métrique. Parcourir les emojis disponibles. |
Exemples
curl -X PUT https://api.logsninja.com/v1/metrics \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"project": "YOUR_PROJECT_ID",
"id": "mrr",
"title": "MRR",
"value": 4900,
"value_type": "currency",
"currency": "EUR"
}'
await fetch('https://api.logsninja.com/v1/metrics', {
method: 'PUT',
headers: {
'Authorization': 'Bearer YOUR_API_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
project: 'YOUR_PROJECT_ID',
id: 'mrr',
title: 'MRR',
value: 4900,
value_type: 'currency',
currency: 'EUR',
}),
});
import requests
requests.put(
'https://api.logsninja.com/v1/metrics',
headers={
'Authorization': 'Bearer YOUR_API_TOKEN',
'Content-Type': 'application/json',
},
json={
'project': 'YOUR_PROJECT_ID',
'id': 'mrr',
'title': 'MRR',
'value': 4900,
'value_type': 'currency',
'currency': 'EUR',
},
)
Supprimer une métrique
https://api.logsninja.com/v1/metrics/:id?project=YOUR_PROJECT_ID
Supprime une tuile métrique du tableau de bord.
Projets
Lister les projets
https://api.logsninja.com/v1/org/projects
Retourne les projets de l’organisation avec pagination. Un token limité à un projet ne reçoit que le projet auquel il est lié. Accepte les paramètres page (1 par défaut) et limit (50 par défaut, 200 maximum). La réponse contient page, limit, total et has_more.
Créer un projet
https://api.logsninja.com/v1/org/projects
La création d’un projet nécessite un token valable pour toute l’organisation. Un token limité à un projet ne peut pas créer de projets.
| Champ | Type | Requis | Description |
|---|---|---|---|
name |
string | ✓ | Le nom du projet. |
Tokens
Lister les tokens
https://api.logsninja.com/v1/org/tokens
Retourne les tokens API de l’organisation avec pagination. Un token limité à un projet ne reçoit que les tokens liés au même projet. Accepte les paramètres page (1 par défaut) et limit (50 par défaut, 200 maximum). La réponse contient page, limit, total, has_more et la capacité can_manage_tokens de chaque token. La valeur des tokens n’est jamais retournée après leur création.
Créer un token
https://api.logsninja.com/v1/org/tokens
Le credential appelant doit avoir can_manage_tokens=true. La valeur du token n’est retournée qu’une fois et ne peut plus être récupérée. Un appelant limité à un projet ne peut créer qu’un autre token pour ce même projet ; omettre project_id ne donne pas accès à toute l’organisation.
| Champ | Type | Requis | Description |
|---|---|---|---|
name |
string | ✓ | Le nom du token. |
project_id |
string | Limite le token à un seul projet. Si omis, le token a accès à tous les projets de l'organisation. | |
can_manage_tokens |
boolean | Autorise ce token à créer et déléguer d’autres tokens dans les limites de son organisation ou de son projet. Désactivé par défaut. |
Autorisation de l'appareil
Permet à un outil CLI ou un agent IA d'obtenir un token API sans qu'un humain n'ait à le copier-coller. L'outil demande un court code et l'affiche à un humain ; un humain disposant déjà d'un compte LogsNinja ouvre un lien et approuve la demande depuis sa propre session de navigateur ; l'outil reçoit alors le token automatiquement. Cela ne crée jamais de compte et ne contourne jamais l'inscription – seul un humain déjà connecté peut approuver une demande.
Démarrer le flux
https://api.logsninja.com/v1/device/authorize
Aucune authentification requise. Retourne un device_code, un court user_code à afficher à l'humain, et un verification_uri à ouvrir dans un navigateur.
{
"device_code": "a1b2c3...",
"user_code": "WXYZ-1234",
"verification_uri": "https://logsninja.com/en/my/tokens#devices",
"verification_uri_complete": "https://logsninja.com/en/my/tokens?user_code=WXYZ-1234#devices",
"expires_in": 600,
"interval": 5
}
Affichez le user_code (ou le lien verification_uri_complete) à l'humain et demandez-lui de l'ouvrir et d'approuver la demande.
Interroger pour obtenir le token
https://api.logsninja.com/v1/device/token
Aucune authentification requise. Interrogez avec le device_code à l'intervalle indiqué ci-dessus jusqu'à ce que le statut ne soit plus pending.
| Champ | Type | Requis | Description |
|---|---|---|---|
device_code |
string | ✓ | Le device_code retourné par l'appel authorize. |
La réponse est {"status": "pending"}, {"status": "denied"}, {"status": "expired"}, ou, une fois approuvée, {"status": "approved", "token": "..."}. Le token n'est retourné qu'une seule fois – stockez-le immédiatement.
Serveur MCP
Permet à un agent IA (Claude, etc.) d'utiliser LogsNinja directement depuis une conversation plutôt qu'en écrivant des appels HTTP.
https://logsninja.com/mcp
Configurez votre client MCP avec cette URL, authentifié avec le même token API que le reste de cette API : Authorization: Bearer YOUR_API_TOKEN.
Claude Code
claude mcp add --transport http logsninja https://logsninja.com/mcp \
--header "Authorization: Bearer YOUR_API_TOKEN"
Claude Desktop
Le fichier de configuration de Claude Desktop n'accepte plus directement le url et les headers d'un serveur distant – uniquement les serveurs stdio (command/args). Faites le pont vers cet endpoint HTTP avec mcp-remote :
{
"mcpServers": {
"logsninja": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://logsninja.com/mcp",
"--header",
"Authorization: Bearer YOUR_API_TOKEN"
]
}
}
}
| Plateforme | Emplacement du fichier de configuration |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
Cursor
Cursor supporte directement le url et les headers d'un serveur distant, sans pont nécessaire :
{
"mcpServers": {
"logsninja": {
"url": "https://logsninja.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_TOKEN"
}
}
}
}
Fichier de configuration : ~/.cursor/mcp.json (global) ou .cursor/mcp.json (projet)
Codex CLI et l'application ChatGPT
Les deux partagent le même ~/.codex/config.toml – le formulaire Paramètres → Plugins → MCPs → Add Server de l'application ChatGPT y écrit aussi. Éditez-le directement pour utiliser bearer_token_env_var, qui lit le token depuis une variable d'environnement au lieu de le stocker en clair :
[mcp_servers.logsninja]
url = "https://logsninja.com/mcp"
bearer_token_env_var = "LOGSNINJA_API_TOKEN"
Définissez la variable d'environnement dans votre profil shell avant de lancer Codex ou l'application ChatGPT, par ex. export LOGSNINJA_API_TOKEN=YOUR_API_TOKEN.
Fichier de configuration : ~/.codex/config.toml
Outils
| Outil | Description |
|---|---|
list_projects, create_project |
Liste les projets accessibles à l’appelant. La création d’un projet nécessite un token valable pour toute l’organisation. |
list_charts, create_chart, update_chart, delete_chart |
Mêmes champs et règles de validation que l'éditeur de graphiques du tableau de bord. |
list_widgets, create_widget, update_widget, reorder_widgets, delete_widget |
Mêmes règles de disposition en mosaïque que les endpoints REST des widgets. |
get_data_inventory |
Noms de streams, titres d'événements et clés de métadonnée connus – utile avant de construire un graphique. |
preview_chart_data |
Calculer les données d'un graphique sans le créer. |
search_emojis |
Rechercher des emojis par nom, shortcode ou mot-clé – utile pour en choisir un pour un event. |
get_documentation |
La documentation complète de l'API en Markdown, dans la langue de votre choix. |
list_events, get_event |
Les 100 derniers events (éventuellement filtrés par stream), ou le détail d'un event avec ses voisins chronologiques. Pas de pagination. |
list_users, get_user |
Les 100 derniers users, ou le détail d'un user par id. Pas de pagination ni de recherche. |
list_streams, list_metrics |
Streams et métriques personnalisées définies dans un projet. |
create_event, delete_event, create_or_update_user, delete_user, create_or_update_metric, delete_metric |
Identique aux endpoints d'ingestion – pensé pour créer et nettoyer des données de test, pas pour envoyer de vrais events de production au nom d'un utilisateur. |
La plupart des tools prennent un argument project_id, requis sauf si le token est limité à un seul projet – même règle que les endpoints REST ci-dessous.
Graphiques
Créez et gérez les mêmes graphiques que vous construiriez à la main sur votre tableau de bord – chaque option ci-dessous et chaque règle de validation est identique, que vous utilisiez l'éditeur de graphiques du tableau de bord ou l'API. Il s'agit uniquement de la configuration du graphique : elle définit ce qu'il affiche, pas ses valeurs calculées – il n'existe pas de endpoint pour récupérer les points de données d'un graphique via cette API.
Types de graphique
Un graphique en ligne (line) trace une valeur par période sous forme de ligne continue – idéal pour suivre une tendance dans le temps. Un camembert (pie) montre un instantané unique découpé en parts – idéal pour une répartition en un coup d'œil. Un graphique en barres (bar) montre une barre par période ; dès que vous ajoutez une répartition (voir « Group by » ci-dessous), il est automatiquement dessiné avec des segments empilés au lieu d'une seule barre – il n'existe pas de type « barres empilées » distinct à choisir. Un graphique en tunnel (funnel) pose un tout autre type de question : au lieu d'une métrique dans le temps, il montre combien des mêmes utilisateurs ont franchi une séquence ordonnée d'étapes.
Plage de temps et intervalle
Choisissez la période couverte par le graphique : les 7 derniers jours (7d), les 30 derniers jours (30d), ou les 90 derniers jours (90d). Vous pouvez aussi définir votre propre fenêtre glissante en heures, jours ou mois (duration, avec periodDurationValue et periodDurationUnit, ex. « les 45 derniers jours »), ou fixer une date de début qui court toujours jusqu'à aujourd'hui (custom, avec periodDateFrom) – il n'existe pas de champ pour une date de fin fixe, ça court toujours jusqu'à aujourd'hui.
L'intervalle de temps (granularity) définit comment cette période est découpée en intervalles : par heure, jour, semaine ou mois (hour, day, week, month). Il ne s'applique pas aux graphiques en tunnel : ils utilisent quand même la plage de temps ci-dessus pour filtrer les événements, mais affichent une barre par étape au lieu d'une série d'intervalles dans le temps.
Certaines combinaisons n'ont que 90 jours d'historique disponibles, quelle que soit la période choisie : un tunnel, un camembert avec une répartition, une répartition par pays/utilisateur/metadata, plus d'une répartition à la fois, tout calcul autre qu'un simple comptage, ou un filtrage par metadata. Un simple comptage sans répartition, ou une répartition uniquement par stream ou titre d'événement, peut remonter plus loin.
Filtrer les événements comptabilisés
Par défaut, un graphique inclut tous les événements (all). Vous pouvez le restreindre à un seul stream (stream, ex. uniquement "payments"), un seul titre d'événement (title, ex. uniquement "Order placed"), ou aux événements correspondant à une valeur de métadonnée précise (metadata, ex. uniquement les événements où "plan" vaut "pro").
| Objectif | Configuration |
|---|---|
| Ne compter que les événements du stream "payments" | event_source_type: "stream", event_source_value: "payments" |
| Ne compter que les événements "Order placed", quel que soit leur stream | event_source_type: "title", event_source_value: "Order placed" |
| Ne compter que les événements où la métadonnée "plan" vaut "pro" | event_source_type: "metadata", event_source_value: "plan=pro" |
Agrégation
Ceci détermine comment les événements correspondants de chaque intervalle de temps deviennent le nombre unique tracé : un simple comptage d'événements (count), un comptage d'utilisateurs uniques (count_distinct), ou un calcul sur une valeur de métadonnée numérique de vos événements – son total (sum), sa moyenne (avg), son minimum (min), son maximum (max), ou sa médiane (median). Pour tout calcul autre qu'un simple comptage, vous choisissez aussi quelle clé de métadonnée contient ce nombre via aggregation_field ; les événements qui ne l'ont pas, ou dont la valeur n'est pas numérique, sont ignorés.
| Objectif | Configuration |
|---|---|
| Événements par jour | aggregation: "count" |
| Utilisateurs uniques actifs par jour | aggregation: "count_distinct" |
| Revenu total par jour (une clé de métadonnée "amount" sur vos événements) | aggregation: "sum", aggregation_field: "amount" |
| Valeur moyenne des commandes par jour (une clé de métadonnée "amount" sur vos événements) | aggregation: "avg", aggregation_field: "amount" |
| Plus petite commande par jour (une clé de métadonnée "amount" sur vos événements) | aggregation: "min", aggregation_field: "amount" |
| Plus grande commande par jour (une clé de métadonnée "amount" sur vos événements) | aggregation: "max", aggregation_field: "amount" |
| Durée médiane de session par jour (une clé de métadonnée "duration_seconds" sur vos événements) | aggregation: "median", aggregation_field: "duration_seconds" |
Grouper par
Par défaut, un graphique affiche une seule valeur agrégée par période. Le regroupement (group_by) le scinde en plusieurs séries ou segments à la place – un par valeur distincte de ce que vous choisissez pour regrouper – dessinés comme des lignes séparées, des segments empilés, ou des parts de camembert selon le type de graphique.
Vous pouvez regrouper par stream (stream), titre d'événement (title), pays (country) ou utilisateur (user) sans rien configurer d'autre, ou par une clé de métadonnée de votre choix (metadata, avec aggregation_field contenant la clé à utiliser pour scinder).
| Objectif | Configuration |
|---|---|
| Événements par jour, une ligne par stream | type: line, aggregation: count, group_by: ["stream"] |
| Quels titres d'événements sont les plus fréquents chaque jour | type: bar, aggregation: count, group_by: ["title"] |
| Inscriptions par jour, réparties par pays | type: bar, aggregation: count_distinct, group_by: ["country"] |
| Comparer l'activité d'une poignée d'utilisateurs précis (votre propre équipe, quelques comptes VIP) – une série par utilisateur correspondant, donc ce n'est lisible que pour un ensemble restreint et délibérément limité | type: line, aggregation: count, group_by: ["user"] |
| Volume d'événements par jour, un segment par plan (une clé de métadonnée "plan" sur vos événements, ex. free/pro/enterprise) | type: bar, aggregation: count, group_by: ["metadata"], aggregation_field: "plan" |
| Répartition des événements par plan, en camembert | type: pie, aggregation: count, group_by: ["metadata"], aggregation_field: "plan" |
Une contrainte à connaître : la clé de métadonnée utilisée pour regrouper et celle utilisée pour agréger sont le même réglage (aggregation_field), puisqu'un graphique n'en a qu'un seul. Donc "montant total des commandes par jour, réparti par plan" n'est pas possible en un seul graphique – il faudrait soit totaliser le montant sans répartition, soit compter les commandes réparties par plan, pas les deux sur le même graphique.
Graphiques en tunnel
Un tunnel (funnel) pose un tout autre type de question : pas « combien d'événements » mais « combien des mêmes utilisateurs sont passés de l'étape 1, à l'étape 2, à l'étape 3 ». Vous lui fournissez une liste ordonnée d'au moins deux titres d'événements via funnel_steps ; le graphique affiche une barre par étape, chacune ne comptant que les utilisateurs ayant aussi complété chaque étape précédente dans l'ordre. La plage de temps ci-dessus s'applique toujours, mais pas la granularité, l'agrégation ni le regroupement.
| Objectif | Configuration |
|---|---|
| Conversion d'inscription : combien ont vu les tarifs, démarré le paiement, puis l'ont terminé | type: "funnel", funnel_steps: ["Pricing viewed", "Checkout started", "Subscription created"] |
Options d'affichage
Vous pouvez afficher ou masquer la légende (show_legend), et choisir vos propres couleurs (colors, un tableau de codes hexadécimaux appliqués dans l'ordre) pour chaque série ou segment au lieu de la palette par défaut. Vous pouvez aussi passer à un total cumulé (cumulative) au lieu d'une valeur par période – pertinent uniquement pour un graphique en ligne ou en barres additionnant un comptage ou une somme, puisqu'un total cumulé d'une moyenne, d'un comptage d'utilisateurs distincts, ou d'un camembert/tunnel n'a pas de sens.
Lister les graphiques
https://api.logsninja.com/v1/org/charts
Accepte un paramètre de requête project_id, requis sauf si le token est déjà restreint à un seul projet.
Créer un graphique
https://api.logsninja.com/v1/org/charts
Modifier un graphique
https://api.logsninja.com/v1/org/charts/{id}
Seuls les champs envoyés sont modifiés.
Supprimer un graphique
https://api.logsninja.com/v1/org/charts/{id}
| Champ | Type | Requis | Description |
|---|---|---|---|
project_id |
string | ✓ | Requis sauf si le token est restreint à un seul projet. |
name |
string | ✓ | Nom du graphique. |
type |
string | ✓ | line, bar, pie, funnel. Il n'existe pas de type « barres empilées » distinct : un graphique en barres avec group_by défini reste de type bar, automatiquement affiché sous forme de segments empilés. |
period |
string | ✓ | 7d, 30d, 90d, duration, custom |
period_date_from |
string | Requis quand period vaut custom, format AAAA-MM-JJ. | |
period_duration_value / period_duration_unit |
integer / string | Requis quand period vaut duration. L'unité est hour, day ou month. | |
granularity |
string | ✓ | hour, day, week, month |
aggregation |
string | ✓ | count, count_distinct, sum, avg, min, max, median |
aggregation_field |
string | Nom du champ de métadonnée, requis pour sum/avg/min/max/median et quand group_by inclut metadata. | |
group_by |
array | N'importe lequel parmi stream, title, country, user, metadata. | |
event_source_type |
string | ✓ | all, stream, title, metadata |
event_source_value |
string | Requis sauf si event_source_type vaut all. | |
funnel_steps |
array | Au moins deux noms d'étapes ordonnés, requis quand type vaut funnel. | |
show_legend / cumulative |
boolean | cumulative n'est pris en compte que pour les graphiques line/bar avec une agrégation count ou sum. | |
colors |
array | Couleurs des séries sous forme de codes hexadécimaux. |
L'historique au-delà de la fenêtre de rétention n'est pas disponible pour les combinaisons qui parcourent les événements bruts (funnel, pie avec un group-by, group-by country/user/metadata, ou toute agrégation autre que count).
Widgets
Gérez quelles tuiles apparaissent sur le tableau de bord et comment elles sont disposées – il s'agit uniquement de la configuration de la disposition, pas des données affichées dans une tuile.
Le tableau de bord est une disposition en mosaïque (masonry), pas une grille rigide. Les widgets « petits » (metric, online_users) sont pensés pour occuper un tiers ou la moitié de la ligne (width 1 ou 2) et s'affichent avec exactement la moitié de la hauteur visuelle des widgets « grands » (chart, world_map, events_7d, top_countries), pensés pour occuper la moitié de la ligne ou la ligne entière (width 2 ou 3). Gardez cela en tête en agençant un tableau de bord via l'API.
Lister les widgets
https://api.logsninja.com/v1/org/widgets
Accepte un paramètre de requête project_id, requis sauf si le token est déjà restreint à un seul projet.
Ajouter un widget
https://api.logsninja.com/v1/org/widgets
| Champ | Type | Requis | Description |
|---|---|---|---|
project_id |
string | ✓ | Requis sauf si le token est restreint à un seul projet. |
type |
string | ✓ | metric, chart, events_7d, world_map, top_countries, online_users. Un seul widget de chaque type natif (events_7d/world_map/top_countries/online_users) peut exister par tableau de bord. |
metric_id |
string | Requis quand type vaut metric. Doit être un id de métrique existant. | |
chart_id |
string | Requis quand type vaut chart. Doit être un graphique du même projet. | |
width |
integer | 1 (1/3), 2 (1/2, par défaut), ou 3 (pleine ligne). |
Redimensionner ou déplacer un widget
https://api.logsninja.com/v1/org/widgets/{id}
Envoyez width et/ou position (index commençant à 0 parmi les widgets du projet). Définir une position déplace le widget à cet endroit et décale d'un cran tous les widgets suivants – ça ne permute pas deux widgets. Seuls les champs envoyés sont modifiés.
Réorganiser tout le tableau de bord
https://api.logsninja.com/v1/org/widgets/reorder
Envoyez order comme la liste ordonnée complète de tous les id de widgets du projet (une liste partielle est rejetée), et éventuellement widths comme une correspondance id → width.
Retirer un widget
https://api.logsninja.com/v1/org/widgets/{id}
Codes de réponse
| Endpoint | Succès | Corps |
|---|---|---|
POST /v1/events |
201 | { "id": "...", "image_count": 0, "images_status": "none", "notification_queued": true } |
DELETE /v1/events/:id |
200 | { "ok": true } |
PUT /v1/users |
200 | { "id": "..." } |
DELETE /v1/users/:id |
200 | { "ok": true } |
POST /v1/ping |
200 | { "ok": true } |
PUT /v1/metrics |
200 | { "id": "..." } |
DELETE /v1/metrics/:id |
200 | { "ok": true } |
Codes d'erreur : 400 erreur de validation, 401 token manquant ou invalide, 403 token restreint à un autre projet, 404 projet introuvable.
Référence des emojis
1837 emojis pris en charge
smileys et émotion
souriant
affectueux
avec la langue
avec les mains
neutre / sceptique
somnolent
malade
avec des chapeaux
avec des lunettes
concerné
négatif
costumés et créatures
visages de chat
visages de singe
cœurs
émotions
les gens et le corps
doigts ouverts
signes de la main
pointage du doigt
doigts fermés
mains
accessoires à main
parties du corps
personnes
gestes
rôles et carrières
fantaisie
activités
athlétisme
repos
famille
symboles de personnes
animaux et la nature
mammifères
oiseaux
amphibiens
reptiles
vie marine
insectes
fleurs
d’autres plantes
nourriture et boissons
fruit
légumes
cuit / préparé
asiatique
bonbons
boisson
vaisselle
voyages et lieux
globes et cartes
emplacements géographiques
bâtiments
édifices religieux
d’autres endroits
transport terrestre
transport par eau
transport aérien
hôtel
temps
meteo
activités
événements et jours fériés
médailles de prix
des sports
jeux et passe-temps
arts et métiers
objets
vêtements
bruit
musique
instruments de musique
téléphone
ordinateur
lumière, film et vidéo
livres et papier
argent
courrier
écrit
fournitures de bureau
serrure & clés
outils
équipement scientifique
médical
articles ménagers
d’autres objets
symboles
panneaux de transport
symboles d’avertissement
flèches
symboles religieux
signes du zodiaque
symboles audio et vidéo
signes de genre
symboles mathématiques
ponctuation
devises
d’autres symboles
caractères de clavier
symboles alphanumériques
formes et couleurs
drapeaux
autres drapeaux
drapeaux de pays
