Ludex ingestion — quickstart
Send your first telemetry event in a few minutes using direct HTTP. The ingestion API is the canonical integration surface; game engines and SDKs use the same JSON contract.
What you need
- Base URL —
https://ingest.ludexstudio.com(replace with the URL Ludex gives you if it differs). - API key issued for a specific organization, project, and environment (environment identifier string must match the
environmentfield in every request body). - Scopes on the key:
ingest:eventsforPOST /v1/ingest/eventingest:batchforPOST /v1/ingest/batch
HTTP-first integration
Direct HTTP is the primary integration path: same JSON contract, Authorization: Bearer, and 202 semantics documented here and in contract-reference.md. This works from any language or engine.
Optional thin clients:
- Unity — an official package targets the same
/v1/ingest/*endpoints; use it when you prefer C# in-editor over raw HTTP. - Unreal / other engines — ship HTTP from your stack (see C++ examples); a dedicated Unreal plugin is planned but not yet available.
Five-minute integration test
Use this as an end-to-end sanity check once you have your API key and project identifiers. Substitute the real values Ludex provided.
- Health —
curl -sS "{INGEST_BASE}/v1/health"and confirm a healthy JSON payload (same check as in Verify the API is up below). - First event — send a single event to
{INGEST_BASE}/v1/ingest/eventwith your API key,project_id, andenvironment. Expect HTTP 202 and JSON with"status":"accepted"(and anevent_id). - If something fails — use error-catalog.md for codes; re-check
project_id,environment, and scopes on the key.
1. Verify the API is up (optional)
curl -sS "https://ingest.ludexstudio.com/v1/health"
Expect JSON like {"status":"ok","message":"Healthy"}.
2. Send one event (curl)
Replace placeholders with your real values.
curl -sS -X POST "https://ingest.ludexstudio.com/v1/ingest/event" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"project_id": "YOUR_PROJECT_ID",
"environment": "YOUR_ENVIRONMENT_ID",
"event": {
"event_name": "pilot_hello",
"timestamp": "2026-04-13T12:00:00.000Z",
"player_id": null,
"session_id": null,
"platform": "curl",
"properties": { "source": "quickstart" },
"sdk": { "name": "curl", "version": "1.0" }
}
}'
Success is HTTP 202 with a body like:
{
"status": "accepted",
"request_id": "…",
"event_id": "…",
"duplicate": false
}
- If you omit
event.event_id, the server generates a UUID and returns it asevent_id. - If you send a stable
event_idand the same raw payload was already stored for that id, you may getduplicate: true(still 202).
3. Common mistakes
| Symptom | Likely cause |
|---|---|
401 with auth_failed |
Missing Authorization: Bearer, wrong key, revoked/expired key |
403 project_mismatch |
project_id in JSON ≠ project bound to the API key |
403 environment_mismatch |
environment in JSON ≠ environment id on the credential |
403 insufficient_scope |
Key missing ingest:events (single) or ingest:batch (batch) |
| 422 | JSON shape wrong or fields invalid (see contract-reference.md) |
Full status and error reference: error-catalog.md.
4. Next steps
- Contract: field-by-field reference — contract-reference.md
- Examples: curl, Python, C#, C++ — see the Examples section in the documentation nav (e.g. curl).
- OpenAPI: run the API and open
/docs(Swagger) or/redocfor interactive exploration
5. Idempotency (safe retries)
For exactly-once HTTP response replay (per key, per credential scope), send:
Idempotency-Key: <opaque string, e.g. UUID>
The server caches the 202 response for a bounded TTL (default 300 seconds). Replays with the same key return the cached body. Use this when retrying after timeouts or ambiguous network failures.
Correlation for your own tracing (optional):
X-Correlation-Id: <your trace id>
X-Request-Id: <optional; also used in server logs if provided>
Direct HTTP is always supported. Engine-specific SDKs, if you use them, are thin clients over this same contract.