curl examples — Ludex ingestion
Replace placeholders before running:
| Placeholder | Meaning |
|---|---|
BASE_URL |
https://ingest.ludexstudio.com (or the URL Ludex provides) |
API_KEY |
Bearer token from Ludex (scopes must include the endpoint you call) |
PROJECT_ID |
Must match the credential’s project_id |
ENVIRONMENT |
Must match the credential’s environment_id (same string the platform stores on the key) |
All routes are under /v1. Successful accepts return 202.
Single event — POST /v1/ingest/event
Requires scope ingest:events.
curl -sS -X POST "${BASE_URL}/v1/ingest/event" \
-H "Authorization: Bearer ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"project_id": "'"${PROJECT_ID}"'",
"environment": "'"${ENVIRONMENT}"'",
"event": {
"event_name": "level_complete",
"timestamp": "2026-04-13T12:00:00.000Z",
"player_id": "player-uuid-123",
"session_id": "session-abc",
"platform": "Windows",
"build_version": "1.0.0",
"game_version": "0.9.2",
"event_id": "550e8400-e29b-41d4-a716-446655440000",
"properties": {
"level": 3,
"score": 1200
},
"sdk": { "name": "curl-example", "version": "1.0.0" }
}
}'
Omit event_id to let the server generate a UUID (recommended for one-off tests; for production clients, prefer a stable client-generated id per logical event for retries).
Single event with optional headers
Idempotency-Key— replays within the server TTL return the cached 202 body (default cache TTL is 300 seconds per process).X-Correlation-Id— propagated for traceability.X-Request-Id— used in structured logs when present.
curl -sS -X POST "${BASE_URL}/v1/ingest/event" \
-H "Authorization: Bearer ${API_KEY}" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: my-first-event-$(date +%s)" \
-H "X-Correlation-Id: corr-demo-001" \
-H "X-Request-Id: client-req-001" \
-d '{
"project_id": "'"${PROJECT_ID}"'",
"environment": "'"${ENVIRONMENT}"'",
"event": {
"event_name": "tutorial_started",
"timestamp": "2026-04-13T12:00:00.000Z",
"properties": {}
}
}'
Batch — POST /v1/ingest/batch
Requires scope ingest:batch. Maximum 5000 events per request (default server limit).
curl -sS -X POST "${BASE_URL}/v1/ingest/batch" \
-H "Authorization: Bearer ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"project_id": "'"${PROJECT_ID}"'",
"environment": "'"${ENVIRONMENT}"'",
"events": [
{
"event_name": "match_started",
"timestamp": "2026-04-13T12:00:01.000Z",
"session_id": "sess-1",
"properties": { "mode": "ranked" }
},
{
"event_name": "match_ended",
"timestamp": "2026-04-13T12:15:00.000Z",
"session_id": "sess-1",
"properties": { "duration_sec": 900, "result": "win" }
}
]
}'
Batch with idempotency
Use the same key only when you intend the entire batch to be treated as one logical submit (cached response applies to that key + credential scope).
curl -sS -X POST "${BASE_URL}/v1/ingest/batch" \
-H "Authorization: Bearer ${API_KEY}" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: nightly-export-batch-2026-04-13" \
-d @batch-payload.json
Put the JSON body in batch-payload.json with the same project_id / environment / events shape as above.
Inspecting HTTP status
Add -w "\n%{http_code}\n" to print the status line after the body:
curl -sS -o body.json -w "%{http_code}\n" -X POST "${BASE_URL}/v1/ingest/event" \
-H "Authorization: Bearer ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{"project_id":"'"${PROJECT_ID}"'","environment":"'"${ENVIRONMENT}"'","event":{"event_name":"ping","timestamp":"2026-04-13T12:00:00Z","properties":{}}}' \
&& cat body.json
Expected: 202 with a JSON body describing acceptance (see contract-reference.md).
Related docs
- contract-reference.md — full field reference
- error-catalog.md — status codes,
codevalues, retries