Development Profile API
The Development Profile API lets an authenticated user read their own development profile — a periodically regenerated coaching summary derived from the codebook of recurring patterns found in that user’s evaluated sessions. It has two parts: a coach’s note carrying the one insight the data does not state on its own, and a list of skills carrying the current state and direction of each one.
The endpoint is implemented in DevelopmentProfileController and is mounted under /api/development-profile.
It operates on the profile of the currently authenticated user (resolved via UserService.currentUser) and
therefore requires a valid JWT bearer token (see Authentication).
The user id is always taken from the authenticated principal, never from the request, so a consumer can only
ever read their own profile.
The profile itself is authored by an LLM tool-loop after a session and stored as a DevelopmentProfile document
(one per user per project); this API only reads the latest stored version.
A profile is rebuilt only when the evidence behind it has actually moved, so generatedAt can be older than the
user’s last conversation without anything being wrong — an unchanged profile means the latest sessions said
nothing new about this person, not that the profile is stale. Poll it after a conversation ends rather than
during one; if you cache it, key the cache on generatedAt.
|
Every string a reader sees is authored in the profile’s own language, including the section headings and the
direction labels in The same applies to Enumerations (
|
GET /api/development-profile
Return the current user’s development profile for a given project.
A profile only exists once the project’s codebook has accumulated enough coded occurrences to generate one, so a brand-new user or project will not have one yet. In that case the endpoint returns 200 OK with an empty body rather than an error — the absence of a profile is a normal state, not a failure.
Query Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
|
Yes |
UUID |
The project whose profile to read. The profile is looked up by the pair ( |
Takes no path parameters and no request body.
Response
Returns a DevelopmentProfile object (see DevelopmentProfile Object) when one
exists, or an empty body (200 OK) when the user has no profile for the project yet.
{
"advisor": {
"name": "Jan Novak",
"periodStart": "2026-06-01",
"periodEnd": "2026-08-27",
"sessionsEvaluated": 94,
"evaluatedDays": 38
},
"generatedAt": "2026-09-11T09:10:40.081Z",
"model": "gpt-5.4",
"language": "cs",
"labels": {
"coachNoteHeading": "Co ti chci říct",
"skillsHeading": "Tvoje dovednosti",
"successCriterionLead": "Poznáš to podle:",
"direction": {
"Solved": "VYŘEŠENO",
"Up": "↑ ROSTE",
"Holding": "= DRŽÍ",
"Flat": "= STOJÍ",
"Risk": "↓ RIZIKO"
}
},
"header": {
"periodSummary": "1. 6. – 27. 8. · 94 hovorů · 38 hodnocených dnů",
"badge": { "label": "Dvě věci vyřešené, jedna stojí", "sentiment": "Positive" },
"dataMaturity": null
},
"coachNote": {
"title": "Otázky kladeš líp, ale na špatném místě hovoru",
"text": "Za tři měsíce jsi udělal dvě věci, které bych nečekal tak rychle ...\n\nDůvod je tenhle: když klient přinese konkrétní detail ...\n\n> Takže příště: až klient řekne něco konkrétního, zůstaň u toho celou další otázku.",
"successCriterion": "ve třech rozborech po sobě zazní po každém detailu otázka ke stejné lince."
},
"skills": [
{
"id": "formulace_otazek",
"direction": "Solved",
"label": "Formulace otázek",
"detail": "Sedmnáct hodnocených dnů po sobě proběhlo bez jediného výskytu.",
"value": null,
"since": "naposledy 14. 7.",
"action": null
},
{
"id": "empatie",
"direction": "Up",
"label": "Empatie",
"detail": null,
"value": "41 → 63 / 100",
"since": "zlom kolem 20. 7.",
"action": null
},
{
"id": "otevreni_hovoru",
"direction": "Holding",
"label": "Otevření hovoru",
"detail": "Drží se bez výpadku v každém hovoru.",
"value": null,
"since": "38 dnů",
"action": null
},
{
"id": "hloubka_po_detailu",
"direction": "Flat",
"label": "Hloubka po detailu",
"detail": null,
"value": "52 → 54 / 100",
"since": "beze změny od 1. 6.",
"action": null
},
{
"id": "bezpeci_u_rizika",
"direction": "Risk",
"label": "Bezpečí u rizikového výroku",
"detail": "Po pěti čistých týdnech se to vrátilo třikrát za posledních čtrnáct dnů.",
"value": null,
"since": "naposledy včera",
"action": "uznat závažnost, ověřit význam, zjistit bezpečí — teprve pak dál"
}
]
}
The example above shows every direction value and both the populated and the null case of every optional
field. header.dataMaturity is non-null only while the window is still too short to compare periods, for
example "1. týden — na srovnání brzy"; coachNote.successCriterion may be absent when the note states no
measurable outcome.
Response Objects
DevelopmentProfile Object
| Field | Type | Description |
|---|---|---|
|
Object |
Machine-readable period facts (see Advisor Object) — computed by the service, never authored. |
|
Instant |
Timestamp of the run that last produced this profile content. |
|
String |
Identifier of the LLM that generated the profile. |
|
String |
Language tag of every authored string, as reported by the model (e.g. |
|
Object |
The UI strings for that language (see Labels Object). Stable across regenerations. |
|
Object |
Period line and trajectory badge (see Header Object). |
|
Object |
The coach’s note (see CoachNote Object). |
|
Array |
2–8 skill rows (see Skill Object), in the order they should be rendered. |
Advisor Object
| Field | Type | Description |
|---|---|---|
|
String |
Display name of the coached user. |
|
String |
ISO date of the first coded occurrence in the window. |
|
String |
ISO date of the last one. |
|
Integer |
Distinct sessions behind the profile. |
|
Integer |
Distinct calendar days on which the user was evaluated. |
Labels Object
| Field | Type | Description |
|---|---|---|
|
String |
Heading to render above |
|
String |
Heading to render above |
|
String |
Lead-in to render before |
|
Object |
Display text per |
Header Object
| Field | Type | Description |
|---|---|---|
|
String |
Finished, localised period sentence — render as given. |
|
Object |
Trajectory badge (see Badge Object). |
|
String or null |
Present only while the window is too short to compare periods. |
Badge Object
| Field | Type | Description |
|---|---|---|
|
String |
Short present-tense label naming the trajectory. |
|
String |
One of |
CoachNote Object
| Field | Type | Description |
|---|---|---|
|
String |
The point of the note in one line. Plain text. |
|
String |
The note itself, in Markdown — see below. |
|
String or null |
How the reader will know it worked. |
text is the only Markdown field in the profile; everything else, title included, is plain text. It holds 2–3
prose paragraphs separated by a blank line, and always ends with what to do in the next conversation as a
blockquote (> …). title and text together are at most 1400 characters. Render it through a Markdown
renderer: the paragraph breaks and the closing quote are part of how the note reads, and a client that prints
the raw string shows the reader a stray >.
Skill Object
| Field | Type | Description |
|---|---|---|
|
String |
Stable snake_case key; the same skill keeps its id across regenerations. |
|
String |
One of |
|
String |
Short skill name. |
|
String or null |
One whole sentence of context, capitalised and closed with a period. The only row
field written as a sentence — |
|
String or null |
A figure worth showing, already formatted, e.g. |
|
String or null |
When it last moved or was last seen. |
|
String or null |
What to do about it. Always present for |