Anbindungen

BI-Datensätze

KI zu dieser Seite fragen

Das Reporting veröffentlicht Datensätze: Tabellen mit abgestimmten Kennzahlen, etwa freigegebene Stunden pro Person und Tag. Ein Business-Intelligence-Werkzeug (Power BI, Tableau, Looker Studio oder ein eigenes Skript) liest sie mit einem API-Schlüssel über die öffentliche API. Die Zahlen entsprechen denen in den Berichten von Akollo. Das Werkzeug liest nur; es ändert nie etwas in Akollo.

1. Schlüssel anlegen

API keys öffnen

Öffnen Sie Integrations → API keys (API-Schlüssel).

Schlüssel benennen

Geben Sie dem Schlüssel einen Namen, der das nutzende Werkzeug erkennen lässt, zum Beispiel „Power BI – Finanz-Workspace“.

Dienstkonto wählen

Wählen Sie das Service account (Dienstkonto), in dessen Namen das Werkzeug handelt. Das Dienstkonto muss Berichtsdatensätze lesen dürfen.

Berechtigung setzen

Setzen Sie unter Scopes die Berechtigung reports.dataset (BI-Datensätze, nur lesend) auf Read. Lassen Sie alle anderen Berechtigungen auf None, sofern das Werkzeug nicht auch diese Datensätze braucht.

Ablaufdatum und Adressen festlegen

Legen Sie ein Ablaufdatum fest. Ruft das Werkzeug immer von denselben Adressen auf, tragen Sie diese ein.

Schlüssel kopieren

Kopieren Sie den Schlüssel, sobald er angezeigt wird. Er wird nur einmal angezeigt.

Ein Schlüssel mit nur dieser Berechtigung kann weder Projekte, Aufgaben noch Personen lesen und nichts ändern.

2. Datensätze auflisten

curl https://<akollo-host>/api/public/v1/datasets \
  -H "Authorization: Bearer <api key>" \
  -H "Akollo-Version: 2026-09-24"

Die Antwort listet jeden Datensatz, den der Schlüssel lesen darf, mit seiner Version:

{ "data": [ { "key": "hours.daily", "version": 2 } ] }

Die Version steigt, wenn sich die Spalten eines Datensatzes ändern. Eine leere Liste bedeutet, dass Ihre Organisation dem Dienstkonto dieses Schlüssels noch keine Datensätze zugewiesen hat. Bitten Sie Ihre Reporting-Administration um die Freigabe.

3. Zeilen seitenweise lesen

curl "https://<akollo-host>/api/public/v1/datasets/hours.daily/rows" \
  -H "Authorization: Bearer <api key>" \
  -H "Akollo-Version: 2026-09-24"
{
  "data": [ { "person": "…", "date": "2026-09-01", "approved_hours": 7.5 } ],
  "has_more": true,
  "next_cursor": "eyJ…",
  "dataset": { "key": "hours.daily", "version": 2 }
}
Einen Datensatz seitenweise lesen
  • Jede Zeile ist ein flacher Datensatz. Ein Wert ist Text, eine Zahl, wahr/falsch oder leer.
  • Solange has_more true ist, fragen Sie erneut mit ?cursor=<next_cursor> an. Die Antwort enthält außerdem einen Link-Header mit rel="next", der dieselbe Adresse enthält. Folgen Sie ihm unverändert.
  • Wie viele Zeilen eine Seite enthält, bestimmt das Reporting. Der Feed akzeptiert weder limit noch $top oder $select.
  • Um nur einen Teil eines Datensatzes zu lesen, ergänzen Sie $filter (siehe unten). Behalten Sie denselben $filter auf jeder Seite bei; der Link-Header enthält ihn bereits.
  • Ein Cursor gehört zu genau einem Datensatz, einer Version, einem $filter und dem Schlüssel, der ihn erhalten hat. Ändert sich die Version des Datensatzes während des Blätterns oder senden Sie den Cursor mit einem anderen Schlüssel (etwa nach dem Erneuern des Schlüssels), antwortet der nächste Aufruf mit 400 CURSOR_INVALID. Beginnen Sie dann wieder mit der ersten Seite.

Filtern mit $filter

$filter grenzt die Zeilen ein, die das Reporting dem Schlüssel ohnehin zeigt; es erweitert sie nie. Der Filter ist eine Folge von Vergleichen, verbunden mit and:

<column> <operator> <value> and <column> <operator> <value> …
  • Spalten sind die eigenen Spaltennamen des Datensatzes (kleingeschrieben, wie in den Zeilen).
  • Operatoren: eq (gleich), ne (ungleich), gt, ge, lt, le (größer, größer oder gleich, kleiner, kleiner oder gleich). Nur Kleinbuchstaben.
  • Werte: Text in einfachen Anführungszeichen (ein Anführungszeichen im Text schreiben Sie doppelt: 'O''Brien'), ganze Zahlen (600, -15), true, false, null (nur mit eq oder ne) und Datumsangaben als YYYY-MM-DD ohne Anführungszeichen.
  • Höchstens 8 Vergleiche und 1 024 Zeichen. or, not, Klammern und Funktionen werden nicht unterstützt.

Beispiele (URL-kodieren Sie den Wert beim Zusammensetzen der Adresse):

$filter=local_date ge 2026-09-01 and local_date lt 2026-10-01
$filter=team_id eq '018f0000-0000-7000-8000-000000000001'
$filter=local_date ge 2026-09-01 and employee_count gt 5

Ein Filter, der eine Spalte nennt, die der Datensatz nicht hat, oder eine Spalte mit einem Wert falschen Typs vergleicht, führt zu 400 VALIDATION_FAILED.

Wenn ein Aufruf abgelehnt wird

AntwortBedeutungWas zu tun ist
401Der Schlüssel ist unbekannt, abgelaufen oder widerrufenSchlüssel neu anlegen oder ersetzen
403 SCOPE_MISSINGDer Schlüssel hat keine Berechtigung für BI-Datensätze, oder das Dienstkonto hat sein Leserecht verlorenBerechtigungen des Schlüssels und Rolle des Dienstkontos prüfen
404 NOT_FOUNDDen Datensatz gibt es nicht, oder dieser Schlüssel darf ihn nicht lesenDatensatzschlüssel mit der Liste abgleichen
400 VALIDATION_FAILEDEin nicht unterstützter Abfrageparameter wie limit oder ein $filter außerhalb der obigen RegelnNur cursor und $filter senden; Spalten und Werte des Filters prüfen
400 CURSOR_INVALIDDer Cursor ist beschädigt, wurde mit einem anderen Schlüssel erhalten, oder der Datensatz hat die Version gewechseltWieder mit der ersten Seite beginnen
429Zu viele Aufrufe in einer MinuteDie in Retry-After genannte Zeit abwarten
502 integrations.bi.feed_driftDas Reporting hat Daten in unerwarteter Form geliefert; es wurden keine Zeilen gesendetSpäter erneut versuchen; bei Wiederholung die Akollo-Administration informieren
503 integrations.bi.feed_unavailableDas Reporting ist für Ihre Organisation ausgeschaltetSpäter erneut versuchen

Power BI Desktop

Wählen Sie Get data → Blank query, öffnen Sie den Advanced Editor und fügen Sie die folgende Abfrage ein. Setzen Sie Host, Datensatzschlüssel und API-Schlüssel ein. Für die geplante Aktualisierung im Power-BI-Dienst lassen Sie den Host wie unten als erstes Argument von Web.Contents und den Pfad in RelativePath stehen. Setzen Sie die Anmeldeinformation der Datenquelle auf Anonymous: Der Schlüssel wird im Header übertragen.

let
    Host = "https://<akollo-host>",
    Dataset = "hours.daily",
    ApiKey = "<api key>",
    GetPage = (cursor as nullable text) =>
        Json.Document(
            Web.Contents(
                Host,
                [
                    RelativePath = "api/public/v1/datasets/" & Dataset & "/rows",
                    Query = if cursor = null then [] else [cursor = cursor],
                    Headers = [Authorization = "Bearer " & ApiKey, #"Akollo-Version" = "2026-09-24"]
                ]
            )
        ),
    Pages = List.Generate(
        () => GetPage(null),
        each _ <> null,
        each if _[has_more] then GetPage(_[next_cursor]) else null
    ),
    Rows = List.Combine(List.Transform(Pages, each _[data])),
    Result = Table.FromRecords(Rows, null, MissingField.UseNull)
in
    Result

Wird die Berichtsdatei weitergegeben, legen Sie den Schlüssel als Power-BI-Parameter ab statt im Abfragetext.

Tableau

Tableau liest den Feed auf einem von zwei Wegen.

  • Web Data Connector. Eine kleine Connector-Seite ruft dieselben zwei Adressen auf: Sie listet die Datensätze für die Tabellenauswahl und liest die Zeilen seitenweise, indem sie next_cursor folgt. Der Schlüssel wird im Authentifizierungsschritt des Connectors eingegeben, nicht in der Seite.
  • Geplanter Extrakt. Ein Skript liest alle Seiten in eine CSV-Datei (oder über die Hyper API von Tableau in eine Hyper-Datei), und Tableau Server oder Tableau Cloud aktualisiert den Extrakt daraus nach Zeitplan. Zum Beispiel:
import csv, os, requests

host = "https://<akollo-host>"
headers = {"Authorization": f"Bearer {os.environ['AKOLLO_API_KEY']}", "Akollo-Version": "2026-09-24"}
url = f"{host}/api/public/v1/datasets/hours.daily/rows"
rows, cursor = [], None

while True:
    page = requests.get(url, headers=headers, params={"cursor": cursor} if cursor else None, timeout=60)
    page.raise_for_status()
    body = page.json()
    rows.extend(body["data"])
    if not body["has_more"]:
        break
    cursor = body["next_cursor"]

with open("hours_daily.csv", "w", newline="", encoding="utf-8") as file:
    columns = sorted({name for row in rows for name in row})
    writer = csv.DictWriter(file, fieldnames=columns)
    writer.writeheader()
    writer.writerows(rows)

Bewahren Sie den Schlüssel in der Umgebung oder einem Secrets-Speicher auf, nie in der Skriptdatei.

Looker Studio

Looker Studio liest den Feed auf einem von zwei Wegen.

  • Community Connector. Ein Apps-Script-Connector ruft dieselben Adressen auf, fragt im Authentifizierungsschritt nach dem Schlüssel (Typ „Key“) und liest die Zeilen seitenweise, indem er next_cursor folgt.
  • Google Sheets nach Zeitplan. Ein Apps Script in einer Tabelle liest die Zeilen über einen zeitgesteuerten Trigger und schreibt sie in ein Tabellenblatt; Looker Studio nutzt diese Tabelle als Quelle. Zum Beispiel:
function pullAkollo() {
  const key = PropertiesService.getScriptProperties().getProperty('AKOLLO_API_KEY');
  const base = 'https://<akollo-host>/api/public/v1/datasets/hours.daily/rows';
  const headers = { Authorization: 'Bearer ' + key, 'Akollo-Version': '2026-09-24' };
  let rows = [];
  let cursor = null;

  do {
    const url = cursor ? base + '?cursor=' + encodeURIComponent(cursor) : base;
    const body = JSON.parse(UrlFetchApp.fetch(url, { headers: headers }).getContentText());
    rows = rows.concat(body.data);
    cursor = body.has_more ? body.next_cursor : null;
  } while (cursor);

  const columns = [...new Set(rows.flatMap((row) => Object.keys(row)))];
  const sheet = SpreadsheetApp.getActive().getSheetByName('hours.daily');
  sheet.clearContents();
  sheet.getRange(1, 1, 1, columns.length).setValues([columns]);
  if (rows.length > 0) {
    sheet
      .getRange(2, 1, rows.length, columns.length)
      .setValues(rows.map((row) => columns.map((name) => row[name] ?? '')));
  }
}

Bewahren Sie den Schlüssel in den Skripteigenschaften auf und geben Sie die Tabelle nur für Personen frei, die die Zahlen sehen dürfen.

Weitere Wege, Daten auszugeben

Neben dem Datensatz-Feed listet Integrations → Data out (Datenausgabe) Exportziele: Azure Blob, Power BI und Analytics SQL. Ist der Azure-Blob-Export eingeschaltet, schreibt Akollo jede Datei einmal in den gewählten Container und ändert sie danach nicht; vorhandene Dateien löscht, ändert oder liest es nie. Um Datensätze direkt aus der Datenbank zu lesen, siehe BI-Werkzeug per SQL anbinden.

Reiter Data out mit den Exportzielen Azure Blob, Power BI und Analytics SQL und ausgeschaltetem Azure-Blob-Export
Data out: Exportziele neben dem Datensatz-Feed.

Bewährte Vorgehensweise

  • Ein Schlüssel pro Werkzeug und pro Workspace, damit sich ein Schlüssel ersetzen lässt, ohne die anderen anzuhalten.
  • Aktualisieren Sie so oft, wie sich die Zahlen ändern, nicht alle paar Minuten. Jeder Aufruf zählt gegen das Minutenlimit des Schlüssels und wird als API-Nutzung erfasst.
  • Ersetzen Sie einen Schlüssel vor seinem Ablauf: Integrations → API keys → Roll hält den bisherigen Schlüssel eine kurze Übergangszeit gültig, während Sie das Werkzeug umstellen.

Achtung

Legen Sie einen API-Schlüssel nie in einer weitergegebenen Berichtsdatei, einer Skriptdatei oder einer Tabelle ab. Nutzen Sie stattdessen einen Parameter, die Umgebung, einen Secrets-Speicher oder die Skripteigenschaften.

Häufige Fragen

Verwandte Seiten

Auf dieser Seite