Diese Seite ist die Quelle für Coding-Agenten, die im Auftrag eines Menschen eine Anwendung gegen die teamspace-API bauen. Oben stehen die Regeln, die für jede Anwendung gelten. Darunter folgen Hinweise je Aufgabe: Zeiten erfassen, offene Punkte bearbeiten, Projektauswertungen anzeigen. Die Angaben sind am 2026-09-10 an einem Testmandanten mit Version 2026.3 geprüft oder stammen aus Anwendungen, die gegen einen echten Server gelaufen sind. Was noch offen ist, steht dabei.
Bevor du anfängst
Quellen, in dieser Reihenfolge:
- Diese Seite. Sie sagt, wie die API sich tatsächlich verhält, auch dort, wo die Beschreibung schweigt.
<server>/api/openapi.json(ab Version 26.2, ohne Anmeldung): Adressen, Filter und Felder. Die Datei ist über 1 MB groß. Werte gezielt die Pfade aus, die du brauchst, statt sie ganz zu lesen. Filter, die nicht im Schema des Objekts stehen, sind eigene Felder eines Mandanten. Verwende sie nicht.<server>/api/api/dto.ts: dieselben Objekte kompakt als TypeScript-Klassen, teils mit Kommentaren.<server>/api/<collection>/metaund…/meta/template(mit Anmeldung): erlaubte Methoden, Filter mit Typ und die Vorlage für neue Objekte samt gültigen Werten.- Die Anleitungen im Thema API, etwa Zeiten über die API anzeigen und buchen und Aufbau der API-Adressen (URL-Struktur).
Was du den Benutzer fragst:
- Server-Adresse: die Adresse, unter der er teamspace im Browser öffnet. Steht im Auftrag nur ein Platzhalter wie
<Server-Adresse>, frag nach. Nimm nie die Angabeserversaus der OpenAPI-Beschreibung, dort kann eine ganz andere Adresse stehen. - Geräte-ID und Token gibt der Benutzer erst in der fertigen Anwendung ein. Bitte ihn, sie dir nicht in den Chat zu schreiben und nicht auf Bildschirmfotos zu zeigen.
- Fachbegriffe ohne eigenes Feld, etwa „Projektleiter“ oder „Budget“. Was damit gemeint ist, legt der Benutzer fest. Siehe Wenn du Projektauswertungen anzeigen willst.
- Den Rahmen: nur lesen oder auch schreiben, wo die Anwendung laufen soll, welche Bibliotheken erlaubt sind.
Feldnamen, Pflichtfelder und gültige Werte fragst du nicht ab. Sie stehen hier, in meta/template oder in der optionsUrl eines Feldes. Geht eine Angabe aus keiner Quelle hervor, frag nach, statt sie zu erfinden.
Was für jede Anwendung gilt
Anmeldung
- Angemeldet wird mit einem Gerätepasswort: Persönliche Einstellungen → Geräte → Neues Gerätepasswort. Der Benutzer braucht dafür die Berechtigung „Synchronisation“.
- Jede Anfrage schickt
Authorization: Basic <base64(Geräte-ID:Token)>. Das Login-Passwort verwendest und speicherst du nie. - Einen Endpunkt „aktueller Benutzer“ gibt es nicht. Den angemeldeten Mitarbeiter liefert
GET <server>/api/device/<Geräte-ID>;depth=1im Felduser, seine ID steht inuser.value. Klappt dieser Aufruf, gilt der Token. externalAccess: trueheißt: Das Gerät gehört einem externen Kontakt, nicht einem Mitarbeiter.- Über die API hat der Benutzer genau die Rechte aus der Oberfläche. Das gilt auch für eine Anwendung, die nur liest: Ihr Token könnte alles, was der Benutzer darf.
Listen und Antworten
- Aufbau:
<server>/api/<collection>;<matrix>?<query>. Steuerung mit Semikolon am Pfad (;limit=100;depth=1), Filter hinter dem Fragezeichen (?date=2026-06-01..2026-06-30&project=123,456). - Seiten: höchstens 100 Einträge je Abruf,
sizeist die Gesamtzahl. Blättere mit;offset=, oder folge in_linksdem Eintrag> nextPage, bis es keinen mehr gibt. Ohne Blättern fehlen Daten, ohne dass es auffällt. - Leere Listen kommen als
"items": null, nicht als[]. Behandlenullals leere Liste. ;depth=1: Einträge einer Liste bleiben Link-Objekte, die Felder stehen unterdata. Ohnedepthgibt es nurcaption,hrefundvalue.- Fehlende Felder: Felder ohne Wert können ganz fehlen statt
nullzu sein, am Projekt zum BeispielplannedMinutes. Prüf auf beides. - Voreinstellungen: Manche Listen filtern ohne Angabe.
/api/projectliefert nur aktive Projekte ohne Vorlagen,/api/timeProjektzeiten und Entwürfe. Die tatsächlich angewandten Filter zeigt_urlin der Antwort. - Filter:
=gleich,*=enthält,von..bisBereich einschließlich beider Grenzen,A,Bmehrere Werte. Ob ein Filter einen Bereich erlaubt, zeigtsearchableRangeinmeta. - Aufzählungen wie Belegstatus oder Zahlungsstatus kommen mit technischem
valueund lesbarercaption, etwa"value": "OPEN_AUTO", "caption": "Offen (auto)". Zeig diecaptionan. - Gültige Werte: Auswahlfelder tragen eine
optionsUrl. Für neue Objekte findest du sie in<server>/api/<collection>/meta/template. Übernimm die Adresse, bau sie nicht selbst. ;evaluate=isBookablefiltert nicht, sondern ergänzt jeden Eintrag umevaluation: true/false. Zum Filtern nimmst du?isBookable=true.- Zeitstempel:
beginundendkommen in UTC (2026-09-10T08:00:00.000+00:00). Andere Felder weichen ab,createDateeines offenen Punkts etwa kommt als2011-02-22 10:16:59.0.
Schreiben
- Verknüpfungen schreibst du als reine ID (
"project": 4711) oder als{ "value": 4711 }. - Zum Ändern lädst du das Objekt per
GETund schickst es vollständig mit dem geänderten Feld perPUTan die Adresse des einzelnen Elements zurück. - Fehlt beim Anlegen ein Pflichtfeld, antwortet der Server mit
403und nennt es inmessage. - Frag den Benutzer, bevor die Anwendung etwas mit Folgen schreibt.
Sicherheit
- Nur
https://-Adressen zulassen. - Geräte-ID und Token nie in den Quelltext. Dauerhaft speichern nur, wenn der Benutzer „Angemeldet bleiben“ wählt.
- Serverdaten immer als Text ausgeben (
textContent), nie als HTML. Ticket-Beschreibungen enthalten zum Beispiel HTML. - Verweisen aus Server-Antworten (
href,optionsUrl,_links) nur folgen, wenn sie auf die eigene Server-Adresse zeigen. Sonst gehen die Zugangsdaten an eine fremde Adresse. - Keine Skripte von fremden Servern laden.
- Bei Fehlern
messageanzeigen, niestacktrace. - Dem Benutzer empfehlen, für die Anwendung ein eigenes Gerätepasswort anzulegen und es nach Tests oder bei Verdacht zu widerrufen.
Mehr dazu in Eigene Web-Anwendungen sicher bauen.
Browserzugriff
Eine Anwendung im Browser darf die API direkt aufrufen, ein eigener Proxy ist nicht nötig. Der Server erlaubt jede Herkunft und den Header Authorization. Die erlaubten Methoden hängen an der Adresse: an Listen wie /api/time GET und POST, an einzelnen Elementen wie /api/issue/{id} GET, PUT und DELETE. Schick die Anmeldung im Header, nicht über Cookies.
Fehlerbilder
| Status | Form | Bedeutung | Was die Anwendung tut |
|---|---|---|---|
401 | reiner Text | Geräte-ID oder Token falsch, Gerät gelöscht | Anmeldung neu abfragen |
403 | JSON mit message | Pflichtfeld fehlt, Datum außerhalb der Schreibberechtigung, fehlende Rechte; auch beim Abruf eines gelöschten Eintrags | message anzeigen, Eingaben behalten |
405 | JSON mit message | Methode an dieser Adresse nicht erlaubt oder ungültige ID in der Adresse | Methode und Adresse prüfen |
500 | Text oder JSON | Fehler im Server, etwa meta ohne Anmeldung oder der Filter ?type= an issue | nicht wiederholen, Anfrage vereinfachen |
Module der Oberfläche und Collections
Die API spricht von Collections, der Benutzer von Modulen. Verwechsle sie nicht: „Offene Punkte“ sind issue, nicht ticket.
| Oberfläche | Collection | Wichtig | Im Hilfecenter |
|---|---|---|---|
| Zeiterfassung, Projektzeiten | time | Pflicht beim Buchen: date, project, area, field | Projektzeiten buchen |
| Rubrik und Bereich | timecategory | an der Buchung als area und field, Werte über optionsUrl | Projektzeiten buchen |
| Offene Punkte | issue | erledigt ist, was ein Erledigt-Datum hat | Einführung in die Offenen Punkte |
| Tickets | ticket | Status aus ticketstate, Beschreibung enthält HTML | Einführung ins Ticketsystem |
| Projekte | project | Plan- und Ist-Werte, Unterprojekte über mainProject | Einführung ins Projektmanagement |
| Projektrollen, Projektberechtigungen | projectrole, project/{id}/projectpermission | Projektleitung über die Rolle mit responsible | Einführung ins Projektmanagement |
| Rechnungen | invoice | Feld project, aber kein Filter danach | Rechnungen stellen und Zahlungen buchen |
| Mitarbeiter | user | ID für worker und assignee | Einführung in Personal & HR |
| Gerätepasswort | device | Anmeldung, Besitzer in user | Authentifizieren |
Wenn du Zeiten erfassen willst
- Mitarbeiter:
GET <server>/api/device/<Geräte-ID>;depth=1, dannuser.value. - Projekte:
GET <server>/api/project;sort=name?isBookable=true&isActive=true&isTemplate=false&isDraft=false. - Rubrik und Bereich:
GET <server>/api/time/meta/template, dann dieoptionsUrlvonareaundfieldaufrufen. Zeig diecaptionzur Auswahl, gebucht wird dervalue. - Zeiten eines Tages:
GET <server>/api/time;depth=1?worker=<id>&date=YYYY-MM-DD. Die Tagessumme ist die Summe vondata.amountüber alle Einträge mitdraftStatusNORMAL.amount,beginundendkönnennullsein. Nachbeginsortiert die App selbst. - Buchen:
POST <server>/api/timemitdate,project,area,field,amount(Minuten) und, wenn gemessen,beginundend.workerdarfst du weglassen, dann gilt der Besitzer des Geräts.
Worauf du achten musst:
amountimmer mitschicken. Der Server berechnet die Dauer nicht aus Beginn und Ende. Ohneamountentsteht eine Buchung ohne Dauer.- Fehlende Pflichtfelder meldet der Server mit
403und „Project is missing!“, „ActivityArea is missing!“ oder „ActivityField is missing!“. Fehltdateoder liegt es außerhalb des erlaubten Zeitraums: „Das Datum liegt außerhalb Ihrer Schreibberechtigungen“. - Weitere Pflichtfelder kann eine Installation verlangen, etwa die Beschreibung. Nennt der Auftrag solche Felder, mach sie in der Anwendung zur Pflicht. Zeig die
messagedes Servers trotzdem in jedem Fall an. - Erfolg ist
201. Die Antwort enthält die angelegte Buchung, der HeaderLocationihre Adresse. - Minuten anzeigen: Rechne erst bei der Anzeige in Stunden um. Eine Buchung von 2 Minuten darf nicht als „0 Std.“ erscheinen.
- Eine Stoppuhr gibt es in der API nicht. Die App merkt sich den Beginn selbst, je Mitarbeiter, und bucht beim Stopp.
Beispiele für jede Anfrage und Antwort stehen in Zeiten über die API anzeigen und buchen.
Wenn du offene Punkte liest oder bearbeitest
- Eigene offene Punkte nach Fälligkeit:
GET <server>/api/issue;depth=1;sort=duedate?assignee=<id>&isDone=false. - Felder unter
data:subject(Betreff),description,type,duedate(Fälligkeit),donedate(Erledigt-Datum),progress(Prozent),priority(in der Oberfläche 1 niedrig bis 9 sehr hoch),state(Status als Freitext),project,assignee. Viele davon könnennullsein. - Typ:
type.valueist einer vonISSUETYPE_TODO,ISSUETYPE_GOAL,ISSUETYPE_PROBLEM,ISSUETYPE_IDEA,ISSUETYPE_NOTE,ISSUETYPE_UNKNOWN. Anzeigen solltest dutype.caption. Die Liste liefert<server>/api/enum/issueType, dort zählt die Groß- und Kleinschreibung. Die OpenAPI-Beschreibung nennt die Werte ohne das PräfixISSUETYPE_. - Überfällig ist ein Punkt mit
duedatein der Vergangenheit und ohnedonedate. Punkte ohne Fälligkeit sind nie überfällig. Soll ihre Position in der Liste feststehen, sortierst du in der App nach. - Nach Typ filtern machst du in der App. Der Filter
?type=endete am Testmandanten mit500, egal mit welchem Wert.
Erledigen: In der Oberfläche macht allein das Erledigt-Datum einen Punkt erledigt, der Fortschritt spielt dafür keine Rolle. Der Haken in der Oberfläche setzt Datum, Uhrzeit und 100 %, siehe Meine offenen Punkte: anlegen & abarbeiten. In der API heißt das Feld donedate, laut OpenAPI-Beschreibung im Format yyyy-MM-dd HH:mm:ss. Geändert wird mit PUT <server>/api/issue/<id>.
Bis das geprüft ist: Frag vor dem Erledigen nach, schick die Änderung und lade den Punkt danach neu. Steht dann ein donedate darin, hat es geklappt. Sonst zeigst du message an.
Wenn du Projektauswertungen anzeigen willst
Plan- und Ist-Werte
Ein Projekt trägt mehrere Plan/Ist-Paare. „Budget“ ist keines davon allein, der Benutzer muss festlegen, welches gemeint ist:
| Paar | Plan | Ist |
|---|---|---|
| Stunden (in Minuten) | plannedMinutes | sumMinutes |
| abrechenbare Stunden (in Minuten) | plannedMinutesBillable | sumMinutesBillable |
| Leistungsstunden (in Minuten) | plannedMinutesPerformance | sumMinutesPerformance |
| Arbeitskosten | plannedWorkingCosts | sumWorkingCosts |
| Kosten | plannedExpenses | sumExpenses |
| Erlöse | plannedIncome | sumIncome |
Zu jedem Paar gibt es …Enabled und …Calculated, etwa plannedMinutesEnabled und plannedMinutesCalculated. Ist kein Planwert gepflegt, fehlt das Feld planned… in der Antwort ganz. Am Testmandanten war plannedMinutesCalculated an einem Hauptprojekt trotzdem gefüllt. Was genau darin steckt, ist noch nicht bestätigt, siehe die offenen Fragen unten.
Unterprojekte
sumMinutesenthält die Unterprojekte. Am Testmandanten ergab ein Hauptprojekt mit 210 eigenen Minuten einsumMinutesvon 2102, genau die Summe über alle Unterprojekte.- Der Filter
projectenthält sie nicht./api/time?project=<Hauptprojekt>liefert nur die Zeiten, die direkt auf dem Hauptprojekt gebucht sind,/api/issue?project=ebenso. - Alle Projekte eines Baums liefert
GET <server>/api/project?mainProject=<id>, das Hauptprojekt selbst eingeschlossen. Nur die direkten Kinder liefert?parent=<id>. Der Matrix-Parameter;parent=wirkt an Projekten nicht. - Für Auswertungen über den ganzen Baum gibst du alle IDs als Mengenfilter mit:
?project=<id1>,<id2>,<id3>. Das gilt für Zeiten, offene Punkte und Tickets.
Stunden je Mitarbeiter und Woche
GET <server>/api/time;depth=1?project=<IDs des Baums>&date=<von>..<bis>, mit Blättern bis zur letzten Seite. Gruppiere in der App nach data.worker.value und der Kalenderwoche von data.date, summiere data.amount der Einträge mit draftStatus NORMAL. Stimmt die Gesamtsumme mit sumMinutes des Hauptprojekts überein, sind Filter und Unterprojekte richtig.
Projektleitung
Ein Feld „Projektleiter“ gibt es nicht, und auch keinen Filter „Projekte, die ich leite“. Am Testmandanten lässt sich die Projektleitung so bestimmen:
- Rollen:
GET <server>/api/projectrole;depth=1. Rollen mitdata.responsible: truesind verantwortlich, am Testmandanten die Rolle „Verantwortlich“. - Gruppen des Benutzers:
GET <server>/api/user/<id>/usergroups. - Berechtigungen je Projekt:
GET <server>/api/project/<id>/projectpermission;depth=1. Jeder Eintrag nenntprojectRole,userGroupund, wenn geerbt,inheritationFromProject. Leitet der Benutzer das Projekt, gibt es einen Eintrag mit einer verantwortlichen Rolle und einer seiner Gruppen.
Das ist eine Anfrage je Projekt. Stell sie parallel und lade nur die Projekte, die du wirklich anzeigen willst.
Offene Punkte und Tickets je Projekt
- Offene Punkte:
GET <server>/api/issue;depth=1?project=<IDs>&isDone=false. - Tickets:
GET <server>/api/ticket;depth=1?project=<IDs>. Der Status indata.stateist ein Verweis auf/api/ticketstatemitcaption, zum Beispiel „In Arbeit“. Die Status legt jede Installation selbst fest. Jeder trägt eineresponsibility:INTERN,EXTERNoderNONE. Am Testmandanten hatten nur die geschlossenen Status („Erfolgreich geschlossen“, „Erfolglos geschlossen“)NONE. Welche Status als offen gelten, frag den Benutzer, bis das bestätigt ist. - Ticket-Beschreibungen enthalten HTML. Gib sie als Text aus oder lass sie weg.
Rechnungen
- Rechnungen haben ein Feld
project, lassen sich aber nicht nach Projekt filtern. LadeGET <server>/api/invoice;depth=1seitenweise und filtere in der App aufdata.project.value. data.statusist der Belegstatus (zum BeispielVALIDATED, „Validiert“),data.payStatusder Zahlungsstatus (zum BeispielOPEN_AUTO, „Offen (auto)“). Zeig jeweils diecaption.data.payStatusOutstandingist der offene Betrag,data.payStatusPayedder bezahlte,data.dueDatedie Fälligkeit.
Wenn du eine React-Anwendung auslieferst
Diese Hinweise stammen aus einer Übersicht für Projektleiter, gebaut mit React und Vite.
- Ein Doppelklick auf
index.htmlfunktioniert nicht. Vite erzeugt JavaScript-Module, und die laden Browser nicht überfile://. Die Seite bleibt leer. Sag das dem Benutzer. - Lokal ansehen:
npm run build, danachnpm run previewim Projektordner. Das Terminal muss offen bleiben. „Verbindung abgelehnt“ im Browser heißt: Es läuft kein Server. - Klappt
localhostnicht, hilfthttp://127.0.0.1:…oder den Server mit--host 127.0.0.1starten. - Veröffentlichen: den Inhalt von
dist/auf einen beliebigen Webserver kopieren. Mit relativem Basispfad (base: './'invite.config) läuft die Anwendung auch in einem Unterverzeichnis. - Nach jeder Änderung wieder
npm run buildunddist/neu hochladen.
Wenn du testest
- Du hast keine Zugangsdaten. Teste mit nachgebauten Daten und sag dem Benutzer, dass der erste Test gegen den echten Server bei ihm liegt. Dabei zeigen sich meist noch Abweichungen.
- Bau aussagekräftige Fehlermeldungen ein: die angefragte Adresse ohne Zugangsdaten, den Statuscode und den Aufbau der Antwort mit Feldnamen und Typen, aber ohne Inhalte. Dann genügt dem Benutzer ein Bildschirmfoto, und du kannst den Fehler gezielt beheben.
- Bau die nachgebauten Daten wie echte Antworten: Einträge als Link-Objekte mit
data, leere Listen mit"items": null, fehlende Felder stattnull. - Teste zwei Fälle: ein Projekt ohne Buchungen, Tickets und offene Punkte und eines mit Daten.
- Vergleich Summen mit teamspace, etwa die gebuchten Stunden gegen
sumMinutesoder die Angabe im Projekt. Stimmen sie, sind Filter und Unterprojekte richtig.
Noch offen: hier fragst du nach
Zu diesen Punkten gibt es noch keine bestätigte Antwort. Frag den Benutzer, statt eine Annahme einzubauen:
- wie ein offener Punkt über die API erledigt wird, bis der Abschnitt oben geprüft ist
- ob die Rolle mit
responsiblein jeder Installation die Projektleitung meint - welche Ticket-Status als offen gelten
- welches Plan/Ist-Paar „Budget“ heißt, und was
…Calculatedenthält
Für Menschen: der Auftrag an die KI
Wer einen Coding-Agenten beauftragt, achtet auf fünf Dinge:
- Die echte Server-Adresse eintragen. Ein stehengebliebener Platzhalter wie
<Server-Adresse>wird leicht übersehen, dann kann die KI die Beschreibung der Installation nicht lesen. - Die Quellen nennen: diese Seite,
<Server-Adresse>/api/openapi.jsonund<Server-Adresse>/api/api/dto.ts. - Zusätzliche Pflichtfelder nennen. Ohne
date,project,areaundfieldbucht der Server keine Zeit, das steht auf dieser Seite. Verlangt eure Installation mehr, etwa eine Beschreibung, gehört das in den Auftrag. - Fachbegriffe festlegen oder Nachfragen ausdrücklich erlauben.
- Den Rahmen nennen: nur lesen oder auch schreiben, wo die Anwendung laufen soll, welche Bibliotheken erlaubt sind.
Vorlage für eine kleine Anwendung
Diese Vorlage stammt aus einer Zeiterfassungs-App, die als einzelne HTML-Datei entstanden ist. Ersetze alle Angaben in spitzen Klammern, bevor du den Auftrag abschickst:
Baue eine Web-Anwendung als einzelne HTML-Datei ohne externe Abhängigkeiten, die sich über die REST-API mit teamspace verbindet. <Was die Anwendung tun soll, in zwei bis drei Sätzen.>
Server-Adresse: <https://eure-installation> (die Adresse, unter der wir teamspace im Browser öffnen)
Lies zuerst den Leitfaden für Coding-Agenten unter https://help.teamspace.de/thema/api/coding-agenten/, dann <Server-Adresse>/api/openapi.json (nur die benötigten Pfade) und <Server-Adresse>/api/api/dto.ts. Verwende immer die eingegebene Server-Adresse, nicht die Angabe unter „servers“.
Anmeldung per Gerätepasswort (Geräte-ID und Token, Basic Auth).
Zusätzliche Pflichtfelder in unserer Installation: <z. B. Beschreibung bei Zeitbuchungen, sonst „keine“>.
Die Anwendung darf: <nur lesen | Zeiten buchen | offene Punkte erledigen>.
Anforderungen: nur https; Zugangsdaten nie im Code und nur nach Zustimmung speichern; Serverdaten immer als Text ausgeben; Fehlermeldungen des Servers anzeigen.
Frage nach, bevor du etwas annimmst, das nicht in den Quellen steht.
Für einen bestehenden Auftrag
Hast du schon einen Auftrag, reicht dieser Satz:
Lies vor dem Programmieren den Leitfaden für Coding-Agenten unter https://help.teamspace.de/thema/api/coding-agenten/ und die OpenAPI-Beschreibung unter <Server-Adresse>/api/openapi.json. Halte dich an die dort beschriebenen Adressen, Pflichtfelder und Regeln. Wenn eine Angabe nicht daraus hervorgeht, frage nach, statt sie zu erfinden.
Zugangsdaten gehören nicht in den Chat mit der KI und nicht auf Bildschirmfotos. Ist das doch passiert, widerruf das Gerätepasswort in den Persönlichen Einstellungen.
Verwandte Themen
- Zeiten über die API anzeigen und buchen API Übungen
- Die OpenAPI-Beschreibung nutzen API Referenz
- Eigene Web-Anwendungen sicher bauen API Konzept
- MCP oder API – was wann? MCP & KI-Agenten Konzept