Custom API Connection

Practical onboarding for your first custom-data API import, including when to prefer API over upload and how status tracking works.

Purpose of this page

This page is the practical guide for your first working import through the integrations API. You learn the flow in clear steps and understand the example JSON without prior API knowledge.

You can get the complete technical contract with all rules and error codes from the internal integration documentation for custom-data imports.

When this connection makes sense

Use this connection when an external system should send data to Zweigen automatically. Typical cases are ERP exports, internal databases, or custom tracking pipelines.

The core benefit is simple: you import server-side, reproducibly, and without manual uploads.

API or upload?

Zweigen offers two entry paths based on the same custom-data import foundation:

  • Custom API Connection: for recurring, automated server-to-server imports
  • CSV/XLSX Upload: for manual setup, one-off imports, or business-prepared files

Both paths end in the same validation and import pipeline. The lanes remain source-separated: sources from the custom_api lane may use the public API contract; sources from the csv_xlsx lane stay in the upload path.

What to prepare

First create a dedicated data source under Data Sources -> Custom API. Without a valid data source, Zweigen cannot assign the import correctly.

You also need:

  • an API key with the permission api.org.customData.ingest
  • a stable Idempotency-Key per semantic import
  • a backend or integration service that sends the request, not browser code
  • a source created specifically for the API lane

Step 1: Send the import request

Send the import to POST /api/integrations/v1/custom-data/imports. The endpoint works asynchronously and responds with 202 Accepted for new requests.

Required headers:

  • Authorization: Bearer <API_KEY>
  • Content-Type: application/json
  • Idempotency-Key: <your-stable-key>

Example body:

{
  "dataSourceId": "550e8400-e29b-41d4-a716-446655440000",
  "dataset": {
    "version": 1,
    "schema": {
      "datasetId": "550e8400-e29b-41d4-a716-446655440000",
      "schemaVersion": 1,
      "name": "Revenue Import",
      "timezone": "UTC",
      "supportedGranularities": ["day"],
      "metrics": [{ "id": "revenue", "label": "Revenue", "dataType": "number", "aggregation": "sum" }],
      "dimensions": []
    },
    "data": [{ "ts": "2026-01-01T00:00:00+00:00", "metric": "revenue", "value": 1234.56 }],
    "meta": {
      "exportedAt": "2026-01-02T09:00:00+00:00",
      "dataSourceId": "550e8400-e29b-41d4-a716-446655440000"
    }
  }
}

Responses:

  • 202: Import was accepted and is being processed.
  • 200: The same idempotency key with an identical payload already existed.

Step 2: Understand the example body

To keep the import stable, every field needs a clear role.

dataSourceId at the top level is the destination of your data. This UUID must belong to an existing data source in your organization.

dataset.schema describes the structure of the dataset: datasetId, schemaVersion, name, timezone, supportedGranularities, metrics, and dimensions.

dataset.data contains the measurements in long format: each row has timestamp (ts), metric ID (metric), and numeric value (value). The timestamp must use ISO format with offset, for example +00:00.

dataset.meta provides export context: exportedAt and dataSourceId, which must stay consistent with the top-level dataSourceId.

Step 3: Query status

Because the import runs asynchronously, you actively poll the status:

GET /api/integrations/v1/custom-data/imports/status with dataSourceId and importRequestId.

Polling rule: every 2 to 5 seconds; stop when the state becomes COMPLETED or FAILED.

Step 4: Handle errors

Handle errors through the error code, not through free text:

  • 401 unauthorized / 403 forbidden: check authentication or permission
  • 409 idempotency_key_mismatch: do not reuse the same key with a changed payload
  • 413 payload_too_large: split the request or reduce the dataset
  • 429 rate_limited: increase the interval and use backoff

Operational rules

  • Use the API for scheduled or recurring imports.
  • Use upload when a person should review the file before import.
  • Keep one source in exactly one lane.
  • Treat only COMPLETED and FAILED as terminal import states.

All Data. One system.

ZweigenZWEIGEN

Zweigen is a self-service BI platform with an integrated data foundation for teams and secure EU-hosted operations.

Contact

We are happy to help and advise. Send us an email at hi@zweigen.cloud or visit our socials.