Die Webanalyse-API ermöglicht die Verwaltung von Websites und Benutzern, den Export von Daten sowie den Aufbau eines eigenen Dashboards.

Die API ist derzeit unversioniert und trägt den Präfix `/api/v0`. Grundlegende Änderungen werden vermieden und sind nicht geplant, können jedoch vorkommen. Alle Nutzer mit einem API-Schlüssel werden rechtzeitig benachrichtigt.


Authentifizierung
--------------
Erstellen Sie in Ihrem Konto einen API-Schlüssel (`[Benutzername im oberen Menü] → API`). Senden Sie den Schlüssel im Header `Authorization` als `Authorization: Bearer [token]`. Verwenden Sie dabei `Content-Type: application/json`. Alle Anfragen liefern JSON zurück, sofern nicht anders angegeben.

Beispiel:

    curl https://meinkonto.stats.wise-relations.com/api/v0/me \
        -H 'Content-Type: application/json' \
        -H 'Authorization: Bearer 2q2snk7clgqs63tr4xc5bwseajlw88qzilr8fq157jz3qxwwmz5'

Ersetzen Sie Schlüssel und URL durch Ihre tatsächlichen Werte.

HTTP-Basic-Auth wird ebenfalls unterstützt; das eignet sich vor allem für Tests im Browser. Lassen Sie den Benutzernamen leer und verwenden Sie den API-Schlüssel als Passwort.

Endpoints geben `401 Unauthorized` zurück, wenn der API-Schlüssel fehlt oder falsch ist, und `403 Forbidden`, wenn er nicht die erforderlichen Berechtigungen besitzt.

Rate-Limit
----------
Das Rate-Limit beträgt 4 Anfragen pro Sekunde. Die aktuellen Werte werden in den Antwort-Headern gemeldet:

    X-Rate-Limit-Limit        Anzahl der Anfragen, ab der das Rate-Limit greift; dieser Wert ist immer gleich.
    X-Rate-Limit-Remaining    Verbleibende Anfragen im aktuellen Zeitraum.
    X-Rate-Limit-Reset        Sekunden bis zur Zurücksetzung des Rate-Limits.


Fehler
------
Fehler werden entweder im Feld `error` oder im Feld `errors` gemeldet. Das Feld `error` enthält immer einen String, zum Beispiel:

    {
        "error": "oh noes!"
    }

Das Feld `errors` enthält ein Objekt mit einer Liste:

    {
        "errors": {
            "key":     ["error1", "error2"],
            "another": ["oh noes!"]
        }
    }

Ein Statuscode im Bereich `2xx` enthält niemals Fehler. Ein Statuscode im Bereich `4xx` oder `5xx` enthält immer entweder `error` oder `errors`, jedoch nie beides. Bei Fehlern können weitere Daten in anderen Feldern enthalten sein.

API-Referenz
-------------
Die API-Referenzdokumentation ist verfügbar unter:

- [/api.json]({{.Base}}/api.json) – OpenAPI 2.0 JSON-Datei.
- Online-Viewer: [RapiDoc][1], [SwaggerHub][2] <!-- too broken for now  [simple HTML][3] -->

[1]: /api2.html
[2]: https://app.swaggerhub.com/apis-docs/Carpetsmoker/GoatCounter/0.1
[3]: /api.html

Kurzübersicht
--------------
Eine Kurzübersicht aller Endpoints:

|                                      |                                                  |
| ----                                 | -----                                            |
| `POST  /api/v0/count`                | Seitenaufrufe zählen                             |
| **Exporte**                          |                                                  |
| `POST  /api/v0/export`               | Neuen CSV-Export erstellen                       |
| `GET   /api/v0/export/{id}`          | Informationen zu einem CSV-Export abrufen        |
| `GET   /api/v0/export/{id}/download` | CSV-Export herunterladen                         |
| **Statistiken**                      |                                                  |
| `GET   /api/v0/stats/total`          | Gesamtzahl der Seitenaufrufe abrufen             |
| `GET   /api/v0/stats/hits`           | Aufruf- und Besucherstatistiken je Pfad abrufen  |
| `GET   /api/v0/stats/hits/{path_id}` | Referrer-Statistiken für einen Pfad abrufen      |
| `GET   /api/v0/stats/{page}`         | Statistiken für Browser, Betriebssystem usw.     |
| `GET   /api/v0/stats/{page}/{id}`    | Detailstatistiken (z. B. Browser-Version)        |
| **Websites**                         |                                                  |
| `GET   /api/v0/sites`                | Websites auflisten                               |
| `PUT   /api/v0/sites`                | Neue Website anlegen                             |
| `GET   /api/v0/sites/{id}`           | Detailinformationen zu einer Website abrufen     |
| `POST  /api/v0/sites/{id}`           | Website aktualisieren                            |
| `PATCH /api/v0/sites/{id}`           | Website aktualisieren                            |
| **Benutzer**                         |                                                  |
| `GET   /api/v0/me`                   | Informationen zum aktuellen Benutzer abrufen     |
| **Pfade**                            |                                                  |
| `GET   /api/v0/paths`                | Übersicht aller Pfade abrufen                    |

<style>table code { white-space: pre-wrap; background-color: inherit; }</style>

Beispiele
--------
Einige Shell-Skript-Beispiele für häufige Anwendungsfälle. Alle Beispiele setzen [curl] voraus, einige benötigen zusätzlich [jq].

[curl]: https://curl.se/
[jq]: https://stedolan.github.io/jq/

### Seitenaufrufe vom Backend senden
Mit `/api/v0/count` können Sie Seitenaufrufe aus Ihrem Backend übermitteln. Das entspricht dem Endpoint `/count`, den die JavaScript-Integration verwendet, bietet jedoch höhere Rate-Limits, erlaubt zusätzliche Felder und ermöglicht das Bündeln mehrerer Seitenaufrufe in einer Anfrage.

Ein einfaches Beispiel:

    {{template "sh_header" .}}

    curl -X POST  "$api/count" \
        --data '{"no_sessions": true, "hits": [{"path": "/one"}, {"path": "/two"}]}'

### Export als CSV
Beispiel für einen Export über die API:

    {{template "sh_header" .}}

    # Neuen Export starten, ID aus dem Antwortobjekt auslesen.
    id=$(curl -X POST "$api/export" | jq .id)

    # Der Export läuft im Hintergrund; warten Sie, bis er abgeschlossen ist.
    while :; do
        sleep 1

        finished=$(curl "$api/export/$id" | jq .finished_at)
        if [ "$finished" != "null" ]; then
            # Export herunterladen.
            curl "$api/export/$id/download" | gzip -d

            break
        fi
    done

Das obige Beispiel enthält aus Gründen der Übersichtlichkeit keine Fehlerbehandlung. Fehler werden wie beschrieben im Feld `error` oder `errors` gemeldet.

Das Export-Objekt enthält einen Parameter `last_hit_id`, der als Paginierungs-Cursor verwendet werden kann, um nur Treffer nach diesem Export herunterzuladen. Das ist nützlich, um Ihre lokale Datenbank regelmäßig zu synchronisieren:

    # Cursor auslesen
    start=$(curl "$api/export/$id" | jq .last_hit_id)

    # Neuen Export ab dem Cursor starten.
    id=$(curl -X POST "$api/export" --data "{\"start_from_hit_id\":$start}" | jq .id)

### Statistiken abrufen
Über den Endpoint `/api/v0/stats/*` können Sie die Dashboard-Statistiken abrufen.

Ein Beispiel ist als [`goatcounter dashboard`][dashboard]-Befehl verfügbar; ein POSIX-Shell-Skript wäre hier zu unübersichtlich.

Im Beispiel werden alle Daten der Einfachheit halber sequenziell abgerufen. In produktiven Anwendungen empfiehlt es sich, mehrere Anfragen parallel zu stellen.

[dashboard]: https://github.com/arp242/goatcounter/blob/master/cmd/goatcounter/dashboard.go
