Skip to content

Released reports of a card

GET
/api/portal/{client_id}/reports/
curl --request GET \
--url http://localhost:8000/api/portal/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/reports/ \
--header 'Authorization: Bearer <token>'

The card’s released Solutions reports, newest release first, paginated (limit / offset).

The signed-in person’s grant on the card in the path. Every route answers 404 while client access is switched off on the environment. 404 card_not_found for a card the account never held — another athlete’s, a card of the account’s own team, or an id that names nothing. 403 access_ended (reason: revoked · team_plan · minor) for a card it held and can no longer open, consent_required when the consent texts changed since the person accepted them (consent again with POST /api/portal/{client_id}/consent/). A partner API key gets 403. 429 past the account’s rate (client_portal, 120/min; the PDFs client_portal_pdf, 20/min).

Only what a coach released is visible, curated on the server: the team’s hidden metrics are absent, the coach’s AI text and internal fields are not sent, and media URLs are signed for two hours.

client_id
required
string format: uuid
lang
string

en · ru · es; default the grant’s language.

limit
integer
offset
integer
Media typeapplication/json
object
count
required
integer
next
required
string
nullable
previous
required
string
nullable
results
required
Array<object>

One released report of the card.

object
id
required
string format: uuid
solution_slug
required
string
title
required

The Solution’s name in ?lang.

string
generated_at
required
string format: date-time
released_at
required
string format: date-time
pdf_url
required

This API’s route for the report’s PDF.

string

Examples

ExampleOneReport

One report

{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": "9d4c3b2a-1f0e-4d5c-8b7a-6e5f4d3c2b1a",
"solution_slug": "running-gait",
"title": "Running Gait Analysis",
"generated_at": "2026-11-01T18:00:00Z",
"released_at": "2026-11-02T10:15:00Z",
"pdf_url": "/api/portal/a1f1c0a2-0000-4000-8000-0000000000aa/reports/9d4c3b2a-1f0e-4d5c-8b7a-6e5f4d3c2b1a/pdf/"
}
]
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string

Example generated

{
"detail": "example"
}
Media typeapplication/json
object
detail
required

access_ended, consent_required, or DRF’s message for a partner API key.

string
reason

With access_ended: why the card no longer opens — revoked, team_plan or minor.

string
client_name
string
team_name
string
consent_version

With consent_required: the version to accept.

string
kinds

With consent_required: the texts to show.

Array<string>

Examples

403 — access ended

The card no longer opens; the page says why and names nothing else of it.

{
"detail": "access_ended",
"reason": "revoked",
"client_name": "Sofia Lebedeva",
"team_name": "North Track Academy"
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string

Examples

Example404—NotACardOfThisAccount

404 — not a card of this account

{
"detail": "card_not_found"
}
Media typeapplication/json
object
detail
required

429 — throttled: this account’s (or address’s) rate for the route is used up; try again after wait seconds, which Retry-After repeats. A route with a limit of its own answers its own code instead, documented there.

string
wait

With throttled: whole seconds until the next request can pass.

integer
nullable

Example generated

{
"detail": "example",
"wait": 1
}