API Ingest
L’endpoint d’ingest est ce que le SDK appelle pour envoyer un event. Tu peux aussi l’appeler directement depuis n’importe quel client HTTP.
POST https://api.pionne.app/ingestAuthentification
Section intitulée « Authentification »X-Pionne-Token: pio_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxSchéma payload
Section intitulée « Schéma payload »{ "exception_type": "TypeError", "message": "undefined is not an object (evaluating 'user.name')", "stack": "TypeError: undefined is not an object\n at ...", "level": "error", "release": "1.0.0", "environment": "production", "platform": "ios", "app_id": "com.acme.app", "tags": { "tier": "pro", "ab_test": "variant_b" }, "user": { "id": "user_a8f2c1" }, "contexts": { "device": { "manufacturer": "Apple", "model": "iPhone 15 Pro", "model_id": "iPhone16,1" }, "app": { "version": "1.0.0", "build": "42", "bundle_id": "com.acme.app" }, "os": { "name": "iOS", "version": "18.2" }, "expo": { "runtime_version": "1.0.0", "update_id": "abc123" } }, "mechanism": { "type": "global", "handled": false }, "breadcrumbs": [ { "category": "navigation", "message": "/checkout", "ts": 1714896000000 }, { "category": "http", "message": "GET https://api.example.com/cart", "ts": 1714896001000, "data": { "status": 200 } } ], "screenshot": "/9j/4AAQSkZJRgABA...", "extra": { "cart_id": 42 }}| Champ | Type | Requis | Description |
|---|---|---|---|
exception_type | string | Oui | Ex: TypeError, Error, custom |
message | string | Oui | Message de l’erreur |
stack | string | null | Non | Stack brute |
level | 'fatal' | 'error' | 'warning' | 'info' | Non | Default error |
release | string | Non mais recommandé | Pour le matching sourcemap |
environment | string | Non | Default production |
platform | 'ios' | 'android' | Oui | Auto par le SDK |
app_id | string | Oui | Bundle ID, sert au pinning |
tags | object | Non | Clés/valeurs scalaires |
user.id | string | Non | Anonyme uniquement |
contexts | object | Non | Auto-rempli par le SDK |
mechanism | object | Non | { type, handled } |
breadcrumbs | array | Non | Max 50 |
screenshot | string | Non | JPG base64 |
extra | object | Non | Données libres |
Response
Section intitulée « Response »202 Accepted
Section intitulée « 202 Accepted »{ "event_id": "evt_a1b2c3", "issue_id": "iss_xxx" }L’event est en file de traitement. Il apparaît dans le dashboard sous quelques secondes.
Codes d’erreur
Section intitulée « Codes d’erreur »| Code | Cause | Solution |
|---|---|---|
400 | Payload mal formé | Vérifie le schéma |
401 | Token invalide ou révoqué | Régénère via /api/projects/{id}/regenerate |
403 | app_id ne match pas le bundle_id pinné | Voir Bundle ID |
413 | Payload trop lourd (souvent un screenshot non compressé) | Baisse screenshotQuality |
429 | Rate limit atteint sur ce token. Réponse inclut Retry-After. Voir Rate limits. | Réduis le sampleRate ou bump maxEventsPerSecond côté SDK. |
Diagnostic SDK — warnings actionnables sur rejet permanent
Section intitulée « Diagnostic SDK — warnings actionnables sur rejet permanent »Depuis v0.8.6 (RN), v0.3.6 (Web/Node), v0.3.3 (PHP/Flutter), tous les SDKs officiels parsent la réponse en 401/403/422 et émettent un console.warn (ou error_log / developer.log selon le runtime) une seule fois par session, même en build prod. Les erreurs réseau restent silencieuses — seuls les problèmes permanents de config sont remontés.
Le warning est formé selon le cas :
| Status | Forme du warning |
|---|---|
401 | [Pionne] Token rejected (401). Check that the project token (starts with "pio_live_…") matches. |
403 (bundle mismatch) | [Pionne] Bundle ID mismatch — your project rejects events from app_id="<envoyé>". Server expected "<masqué>". |
422 | [Pionne] Event rejected (422 validation): <message serveur>. Sent app_id="<envoyé>". |
| Autre 4xx | Générique [Pionne] Event rejected (status=<N>): <message serveur>. |
Pourquoi c’est utile : avant ce changement, un token mal configuré ou un bundle pinning périmé droppait silencieusement tous les events, sans aucun signal dans la console de l’app. Le dev ne s’en rendait compte qu’en cherchant un crash qu’il venait de provoquer et en ne le trouvant pas dans le dashboard. Maintenant, le premier event rejeté surface un message clair dans les logs runtime, même en TestFlight / staging / prod.
Exemple curl
Section intitulée « Exemple curl »curl -X POST https://api.pionne.app/ingest \ -H "Content-Type: application/json" \ -H "X-Pionne-Token: pio_live_xxx..." \ -d '{ "exception_type": "Error", "message": "manual test", "level": "info", "platform": "ios", "app_id": "com.acme.app" }'