Datasets
Datasets are Loguro’s typed event-table pipeline. They are separate from logs and separate from Web Analytics.
Use datasets when you want to send structured business or product records that should be stored as typed columns and queried with aggregations:
- subscriptions created
- invoices paid
- signup funnel steps
- feature usage
- internal operational metrics
- application events that are too structured for free-form logs
A project can have multiple datasets. Each dataset has its own id, name, description, schema, storage path, and query surface.
How it works
- Create a project in Loguro.
- Open the project rail and go to Datasets.
- Create a dataset metadata record. This gives you a
datasetId. - Register that dataset’s immutable schema.
- Ingest records with the project API key and the
datasetId. - Query the specific dataset with a PAT.
Datasets can be created before their schema exists. Until schema registration, the dataset is pending_schema and ingest/query for that dataset returns Dataset schema not found.
There are two authentication surfaces:
| Token | Used for | Project resolution |
|---|---|---|
| Project API key / ingest token | POST /datasets/:datasetId, POST /datasets/:datasetId/batch | The token identifies the project. |
PAT (pat_...) | dataset metadata, schema management, and query APIs | The project slug is in the URL, and Loguro checks that the PAT owner has access. |
That split is intentional. Ingest keys are data-plane credentials. PATs are account-level control-plane credentials.
Quick start
For TypeScript projects, use @loguro/datasets instead of hand-writing the HTTP calls below. It wraps the same create, schema, ingest, and query APIs with inferred types.
Create dataset metadata:
curl -X POST https://logu.ro/api/datasets/local \
-H "Authorization: Bearer pat_xxx" \
-H "Content-Type: application/json" \
--data '{
"name": "Orders",
"description": "Paid orders from billing"
}' Example response:
{
"dataset": {
"id": 13,
"name": "Orders",
"slug": "orders",
"description": "Paid orders from billing",
"schema": null,
"isDefault": false,
"status": "pending_schema"
}
} Register that dataset’s schema:
curl -X POST https://logu.ro/api/datasets/local/13/schema \
-H "Authorization: Bearer pat_xxx" \
-H "Content-Type: application/json" \
--data '{
"fields": {
"country": "string",
"plan": "string",
"amount": "number",
"active": "boolean",
"signup_at": "timestamp"
}
}' Ingest one record into dataset 13:
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": "backend", "request_id": "req_123" },
"country": "RO",
"plan": "pro",
"amount": 42.5,
"active": true,
"signup_at": "2026-06-01T08:00:00Z"
}' Query dataset 13:
curl -X POST https://logu.ro/api/datasets/local/13/query \
-H "Authorization: Bearer pat_xxx" \
-H "Content-Type: application/json" \
--data '{
"range": {
"from": "2026-06-10T00:00:00Z",
"to": "2026-06-10T23:59:59Z"
},
"select": [
{ "field": "country" },
{ "aggregate": "count", "as": "events" },
{ "aggregate": "sum", "field": "amount", "as": "revenue" }
],
"groupBy": ["country"],
"orderBy": [{ "field": "events", "direction": "desc" }],
"limit": 100
}' Example response:
{
"rows": [
{ "country": "RO", "events": "2", "revenue": 62.5 },
{ "country": "US", "events": "1", "revenue": 5 }
],
"dataset": { "id": 13, "name": "Orders", "slug": "orders" }
} Standard fields
Every dataset record must include:
| Field | Type | Required | Notes |
|---|---|---|---|
timestamp | timestamp string | yes | Event time. Must parse as a timestamp. |
context | JSON object | yes | Stored as JSON for debugging and future use. v1 does not filter, group, or aggregate on context. |
Declared schema fields become top-level typed columns.
Important constraints
- A project can have multiple datasets, subject to plan quota.
- Each dataset has exactly one schema.
- Schema creation is immutable. You cannot edit it later.
- Payloads are strict. Extra top-level fields are rejected.
- Missing declared fields are rejected.
- Wrong field types are rejected.
contextmust be an object, not a string, array, or null.- Query API does not accept raw SQL.
- Dataset data is stored and queried separately from logs and Web Analytics.