Data exports CSV · Parquet · JSON Schema

Three documented export formats: CSV for spreadsheets and ad-hoc analysis, Parquet for analytics pipelines, JSON Schema for type-safe integration. Export via the admin UI or the REST API.

Available formats

CSV

Comma-separated, UTF-8 BOM, header row.

  • Excel / LibreOffice ready
  • Streaming, no row limit
  • GDPR art.20 portability

Parquet

Columnar, Snappy-compressed, Arrow-compatible.

  • DuckDB / pandas / Spark
  • 5 to 10× smaller than CSV
  • Best for >1M rows

JSON Schema

JSON Schema draft 2020-12 + signed records.

  • Type-safe integration
  • Generated TypeScript / Python types
  • Versioned, backward-compatible

Export via the admin UI

  1. 1

    Navigate to Data → Exports

    Available to the admin and auditor roles.

  2. 2

    Pick a dataset

    Raw CDR, aggregated KPIs, audit log, agent configuration.

  3. 3

    Filter and choose the format

    Time range, PBX, direction, phone line filters + format dropdown (CSV / Parquet / JSON).

  4. 4

    Download or trigger an async job

    < 10 MB exports stream directly. Larger exports run as background jobs, with email notification when ready.

Export via the REST API

CSV — synchronous

curl -H "Authorization: Bearer <token>" \
  "https://<vm>:8443/api/v1/cdr/export?from=2026-01-01&to=2026-01-31&format=csv" \
  -o cdr-2026-01.csv

Parquet — async job

# 1. Submit the job
curl -X POST -H "Authorization: Bearer <token>" \
  -d '{"from":"2025-01-01","to":"2025-12-31","format":"parquet"}' \
  https://<vm>:8443/api/v1/cdr/export-jobs

# 2. Poll the job
curl -H "Authorization: Bearer <token>" \
  https://<vm>:8443/api/v1/cdr/export-jobs/<job-id>

# 3. Download via the signed URL returned when status=ready

JSON Schema

curl https://<vm>:8443/api/v1/schemas/cdr.json
# Returns a JSON Schema draft 2020-12 document describing the CDR record format.

CDR schema (excerpt)

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://getnatalia.com/schemas/cdr/v1.json",
  "title": "Natalia CDR Record",
  "type": "object",
  "required": ["id", "pbx_alias", "start_at", "duration_s", "direction"],
  "properties": {
    "id":           { "type": "string", "format": "uuid" },
    "pbx_alias":    { "type": "string" },
    "start_at":     { "type": "string", "format": "date-time" },
    "duration_s":   { "type": "integer", "minimum": 0 },
    "direction":    { "enum": ["inbound", "outbound", "internal"] },
    "calling_party":{ "type": "string", "description": "pseudonymised hash for external numbers" },
    "called_party": { "type": "string" },
    "trunk":        { "type": "string" },
    "extension":    { "type": "string" },
    "result":       { "enum": ["answered", "no-answer", "busy", "abandoned"] }
  }
}

The schema is versioned (v1, v2…) and remains backward-compatible: a new field is always added, never replaced. Breaking changes go through a major bump with a 12-month migration window.

Looking for reversibility?

The export procedures above also cover GDPR art.20 portability and the end-of-contract restitution within 30 days.

Reversibility procedure