Dataset Ingest API
Dataset ingest writes structured records to a specific dataset inside a project.
Use the project API key, not a PAT.
For TypeScript projects, @loguro/datasets provides DatasetIngestClient and validates records before sending them. See Datasets — TypeScript SDK.
Endpoints
| Endpoint | Body | Success |
|---|---|---|
POST https://ingest.logu.ro/datasets/:datasetId | one raw record object | 202 Accepted |
POST https://ingest.logu.ro/datasets/:datasetId/batch | array of raw record objects | 202 Accepted |
There is no project slug in the path. The project is resolved from the API key claims. The dataset id selects which schema and storage path to use.
Legacy endpoints without :datasetId are supported for the default dataset:
POST https://ingest.logu.ro/datasets
POST https://ingest.logu.ro/datasets/batch New integrations should use the dataset-specific path.
Headers
Authorization: Bearer YOUR_PROJECT_API_KEY
Content-Type: application/json Optional:
X-Request-Id: req_123
X-Loguro-Dataset-Id: 13 X-Request-Id is stored as __traceId in the worker output. X-Loguro-Dataset-Id is an alternative selector for clients that cannot put the dataset id in the URL.
Single record
curl -X POST https://ingest.logu.ro/datasets/13 \
-H "Authorization: Bearer YOUR_PROJECT_API_KEY" \
-H "Content-Type: application/json" \
--data '{
"timestamp": "2026-06-10T10:58:00Z",
"context": {
"source": "billing-service",
"request_id": "req_123"
},
"country": "RO",
"plan": "pro",
"amount": 42.5,
"active": true,
"signup_at": "2026-06-01T08:00:00Z"
}' Success:
{
"success": true,
"status": "queued"
} Batch records
curl -X POST https://ingest.logu.ro/datasets/13/batch \
-H "Authorization: Bearer YOUR_PROJECT_API_KEY" \
-H "Content-Type: application/json" \
--data '[
{
"timestamp": "2026-06-10T11:00:00Z",
"context": { "source": "billing-service" },
"country": "RO",
"plan": "pro",
"amount": 20,
"active": true,
"signup_at": "2026-06-01T08:00:00Z"
},
{
"timestamp": "2026-06-10T11:01:00Z",
"context": { "source": "billing-service" },
"country": "US",
"plan": "free",
"amount": 5,
"active": false,
"signup_at": "2026-06-02T08:00:00Z"
}
]' Success:
{
"success": true,
"count": 2,
"status": "queued"
} Strict validation
Every record is validated before it enters the dataset queue.
The API rejects:
| Problem | Example error |
|---|---|
| Missing dataset schema | Dataset schema not found |
| Invalid dataset id | Invalid dataset ID |
| Missing project claim in token | Project not found in API token claims |
| Invalid JSON | Invalid JSON body |
| Single body is not an object | Payload must be an object |
| Batch body is not a non-empty array | Batch body must be a non-empty array |
Missing or invalid timestamp | Invalid or missing timestamp |
Missing or non-object context | context must be an object |
| Extra top-level field | Extra field: extra |
| Missing declared field | Missing field: amount |
| Wrong string type | Invalid string field: country |
| Wrong number type | Invalid number field: amount |
| Wrong boolean type | Invalid boolean field: active |
| Wrong timestamp type | Invalid timestamp field: signup_at |
Payload rules
Given this schema:
{
"fields": {
"country": "string",
"amount": "number",
"active": "boolean"
}
} This is valid:
{
"timestamp": "2026-06-10T10:00:00Z",
"context": {},
"country": "RO",
"amount": 12.5,
"active": true
} This is invalid because amount is a string:
{
"timestamp": "2026-06-10T10:00:00Z",
"context": {},
"country": "RO",
"amount": "12.5",
"active": true
} This is invalid because extra is not declared:
{
"timestamp": "2026-06-10T10:00:00Z",
"context": {},
"country": "RO",
"amount": 12.5,
"active": true,
"extra": "not allowed"
} Quota behavior
Dataset records have a separate monthly quota bucket from logs and web events.
Redis keys use:
quota_limit:datasets:<userId>
usage_total:datasets:<userId>:YYYY-MM
usage_delta:datasets:<userId>:YYYY-MM -1 means unlimited.
When quota is exceeded, the API returns 429 with quota details.