// context projectapi

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

  1. Create a project in Loguro.
  2. Open the project rail and go to Datasets.
  3. Create a dataset metadata record. This gives you a datasetId.
  4. Register that dataset’s immutable schema.
  5. Ingest records with the project API key and the datasetId.
  6. 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:

TokenUsed forProject resolution
Project API key / ingest tokenPOST /datasets/:datasetId, POST /datasets/:datasetId/batchThe token identifies the project.
PAT (pat_...)dataset metadata, schema management, and query APIsThe 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:

FieldTypeRequiredNotes
timestamptimestamp stringyesEvent time. Must parse as a timestamp.
contextJSON objectyesStored 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.
  • context must 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.

Next steps

// related

See also