Öffentliche REST API

Tikklok REST API v1

Eine zustandslose, per API-Schlüssel authentifizierte REST API für Drittanbieter-Integrationen. Lesen Sie die Mitarbeiter, Standorte und Leistungsdaten Ihres Unternehmens. Jede Antwort ist JSON.

Basis-URL

https://api.tikklok.appProduktion
http://localhost:8084lokale Entwicklung

Alle Endpunkte sind unter /v1 versioniert. Jede Anfrage muss in Produktion über HTTPS erfolgen.

Authentifizierung

HTTP Basic Auth über HTTPS. Senden Sie einen Authorization-Header mit Ihrer Schlüssel-ID und Ihrem Secret, base64-codiert:

Authorization: Basic base64(KEY_ID:SECRET)
AnmeldedatenFormatHinweise
KEY_IDTK_PUB_LIVE_… (28)Öffentliche Kennung, Großbuchstaben, 16-hex-Endung. Sicher zu protokollieren.
SECRETTK_SEC_LIVE_… (60)Privat. Wird bei der Erstellung genau einmal angezeigt; nur ein SHA-256-Hash wird gespeichert — bei Verlust nicht wiederherstellbar.

Bei fehlgeschlagener Authentifizierung folgt 401 unauthorized. Die API unterscheidet nie zwischen falschem Schlüssel und falschem Secret, um Enumeration zu verhindern.

Beispiel

curl -u TK_PUB_LIVE_A1B2C3D4E5F60718:TK_SEC_LIVE_… \
     https://api.tikklok.app/v1/me

Rate-Limits

BereichLimit
Pro Schlüssel60 Anfragen / Minute · 1000 / Stunde (feste Fenster)
Pro IP, vor Auth20 Anfragen / Minute (bevor Basic Auth geprüft wird)
Pro IP, Auth-Fehler10 Fehler / Minute → vorübergehende Sperre

Bei Überschreitung folgt 429 rate_limited. Warten Sie eine Minute und versuchen Sie es erneut.

Responses & Fehler

Jede Antwort ist JSON mit einem success-Boolean. Fehler tragen zusätzlich eine kurze maschinenlesbare error-Zeichenfolge. Lesezugriffe geben bei fehlenden Daten nie success: false zurück — ein 404-Body bedeutet, dass die Ressource selbst fehlte. Jede Antwort trägt Cache-Control: no-store.

StatuserrorBedeutung
400invalid_roleUnbekannter role-Filterwert.
400invalid_dateFehlendes/ungültiges Datum oder min_date > max_date.
400range_too_largeLeistungszeitraum über 366 Tage.
401unauthorizedFehlende oder ungültige Anmeldedaten.
404not_foundRessource fehlt — oder gehört zu einem anderen Unternehmen (nicht unterscheidbar, absichtlich).
413payload_too_largeAnfrage-Body über 1 MB.
429rate_limitedRate-Limit überschritten.

Geltungsbereich & IDs

Jede Anfrage ist auf das Unternehmen beschränkt, dem der API-Schlüssel gehört. Ressourcen werden über ihre globalen IDs adressiert:

IDBedeutung
company_user_idEine Person in Ihrem Unternehmen (die „Mitarbeiter“-Identität). Stabil, global eindeutig.
location_idEiner der Standorte Ihres Unternehmens. Stabil, global eindeutig.
Das locations[] jedes Mitarbeiters enthält seine location_user_id — den internen Zuweisungsschlüssel — mit dem Sie Stempelvorgänge für diesen Mitarbeiter an diesem Standort ansteuern. Pfadparameter adressieren eine Zuweisung weiterhin über das Paar (company_user_id, location_id). Jede ID in einem Pfad, die nicht zu Ihrem Unternehmen gehört, gibt 404 not_found zurück — identisch zu einer nicht existierenden ID, sodass fremde IDs nicht ausgespäht werden können. Anfrage-Bodies müssen ≤ 1 MB sein (sonst 413 payload_too_large).

Endpunkte

Alle Endpunkte sind GET. Jeder Endpunkt außer /v1/health erfordert Authentifizierung.

GET/v1/healthohne Auth

Verfügbarkeitsprüfung. Keine Authentifizierung.

Antwort 200

{
  "success": true,
  "status": "ok",
  "version": "v1",
  "time": "2026-08-08T14:23:00Z"
}
GET/v1/meAuth

Bestätigt, dass Ihre Anmeldedaten funktionieren, und zeigt, zu welchem Unternehmen sie gehören.

Antwort 200

{
  "success": true,
  "company_id": 1,
  "company_name": "Acme Corp",
  "key_id": "TK_PUB_LIVE_A1B2C3D4E5F60718",
  "key_name": "My Slack integration"
}
GET/v1/employeesAuth

Paginierte Liste der Personen in Ihrem Unternehmen (company_users), jede mit einer knappen Liste der Standorte, denen sie aktiv zugewiesen ist. Owner/Admins erscheinen ebenfalls, mit einem leeren locations-Array, wenn sie keine Zuweisungen haben.

Query-Parameter

ParamStandardHinweise
limit100Begrenzt auf 1–500.
offset0Für die Paginierung.
location_idNur Mitarbeiter, die diesem Standort aktiv zugewiesen sind.
roleUnternehmensrolle: owner, admin, employee. Ungültig → 400 invalid_role.
include_inactive01, um deaktivierte Mitarbeiter einzuschließen.

Antwort 200

{
  "success": true,
  "total": 25,
  "limit": 100,
  "offset": 0,
  "data": [
    {
      "company_user_id": 42,
      "first_name": "Jane",
      "last_name": "Doe",
      "is_active": true,
      "locations": [
        { "location_user_id": 15, "location_id": 7, "location_name": "Main Store" }
      ]
    }
  ]
}
GET/v1/employees/{company_user_id}Auth

Vollständige Details zu einem Mitarbeiter plus jeder Standortzuweisung (aktiv und historisch — jede mit eigenem is_active). Jede Zuweisung enthält ihre location_user_id (den Zuweisungsschlüssel, für Stempelvorgänge über die API). 404 not_found, wenn der Mitarbeiter nicht in Ihrem Unternehmen ist.

Antwort 200

{
  "success": true,
  "data": {
    "company_user_id": 42,
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com",
    "tel": "+32 470 00 00 00",
    "role": "employee",
    "contract": "fixed_schedule",
    "status": "active",
    "is_active": true,
    "created": "2025-01-15 10:30:00",
    "updated": "2025-08-27 14:22:15",
    "locations": [
      {
        "location_user_id": 15,
        "location_id": 7,
        "location_name": "Main Store",
        "role": "staff",
        "function_id": 3,
        "function_name": "Sales",
        "is_user_primary": true,
        "clocking_allowed": true,
        "overtime": true,
        "valid_from": null,
        "valid_to": null,
        "is_active": true
      }
    ]
  }
}
GET/v1/employees/{company_user_id}/locations/{location_id}Auth

Die Zuweisung eines Mitarbeiters an einem Standort. 404 not_found, wenn der Mitarbeiter nicht in Ihrem Unternehmen ist, der Standort nicht in Ihrem Unternehmen ist oder keine Zuweisung zwischen beiden besteht.

Antwort 200

{
  "success": true,
  "data": {
    "company_user_id": 42,
    "location_user_id": 15,
    "location_id": 7,
    "location_name": "Main Store",
    "role": "staff",
    "function_id": 3,
    "function_name": "Sales",
    "is_user_primary": true,
    "clocking_allowed": true,
    "overtime": true,
    "valid_from": null,
    "valid_to": null,
    "is_active": true,
    "created": "2025-01-15 10:30:00",
    "updated": "2025-08-27 14:22:15"
  }
}
GET/v1/employees/{company_user_id}/performanceAuth

Dieselben Leistungsdaten wie der herunterladbare Bericht des Dashboards, als JSON, gruppiert nach Standort. Für jeden Standort, dem der Mitarbeiter zugewiesen ist (oder war), eine Aufschlüsselung pro Tag plus summierte totals. Alle Zahlen sind Stunden (2 Dezimalstellen); overtime_hours kann negativ sein (Unterzeit).

expected_hours = planned − closed − location_holiday − user_holiday − sick · overtime_hours = worked − expected

Query-Parameter (beide erforderlich)

ParamHinweise
min_dateYYYY-MM-DD
max_dateYYYY-MM-DD, ≥ min_date

Ungültiges/fehlendes Datum oder min_date > max_date400 invalid_date. Ein Zeitraum über 366 Tage → 400 range_too_large. 404 not_found, wenn der Mitarbeiter nicht in Ihrem Unternehmen ist. Ein Mitarbeiter ohne Daten im Zeitraum gibt 200 mit einem leeren locations-Array zurück.

Antwort 200

{
  "success": true,
  "data": {
    "company_user_id": 42,
    "employee_name": "Jane Doe",
    "period": { "min_date": "2025-01-01", "max_date": "2025-01-31" },
    "locations": [
      {
        "location_id": 7,
        "location_name": "Main Store",
        "days": [
          {
            "date": "2025-01-06",
            "planned_hours": 8,
            "worked_hours": 7.75,
            "closed_hours": 0,
            "location_holiday_hours": 0,
            "user_holiday_hours": 0,
            "sick_hours": 0,
            "expected_hours": 8,
            "overtime_hours": -0.25
          }
        ],
        "totals": {
          "planned_hours": 40, "worked_hours": 39, "closed_hours": 0,
          "location_holiday_hours": 0, "user_holiday_hours": 0, "sick_hours": 0,
          "expected_hours": 40, "overtime_hours": -1
        }
      }
    ]
  }
}
GET/v1/locationsAuth

Die Standorte Ihres Unternehmens. qr_base64 wird bewusst weggelassen (groß, und das Stempeln erfolgt app-seitig).

Query-Parameter

ParamStandardHinweise
include_inactive01, um deaktivierte Standorte einzuschließen.

Antwort 200

{
  "success": true,
  "data": [
    {
      "location_id": 7,
      "name": "Main Store",
      "street": "Rue de la Paix",
      "house_nr": "42",
      "postal_code": "1000",
      "city": "Brussels",
      "country": "BE",
      "timezone": "Europe/Brussels",
      "is_company_primary": true,
      "latitude": 50.8503,
      "longitude": 4.3517,
      "geo_radius_meters": 100,
      "is_active": true,
      "created": "2024-06-01 09:00:00",
      "updated": "2025-08-27 14:22:15"
    }
  ]
}
GET/v1/locations/{location_id}Auth

Ein Standort, gleiche Objektform wie die Liste. 404 not_found, wenn er nicht in Ihrem Unternehmen ist.

API-Schlüsselverwaltung

API-Schlüssel werden im Tikklok-Dashboard erstellt, aufgelistet und widerrufen (Einstellungen → API-Schlüssel, nur Owner/Admin). Das Secret wird bei der Erstellung einmal angezeigt — kopieren Sie es sofort. Der Widerruf erfolgt sofort.

OpenAPI-Spec

Eine maschinenlesbare OpenAPI-3.0-Beschreibung steht zum Import in Postman, Insomnia oder Client-SDK-Generatoren bereit.

openapi.yaml herunterladen