What the person may send this month
const url = 'http://localhost:8000/api/portal/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/uploads/allowance/';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url http://localhost:8000/api/portal/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/uploads/allowance/ \ --header 'Authorization: Bearer <token>'The coach’s monthly cap (0: uploads are off), this calendar month’s (UTC) uploads whose analysis did not fail, the day the count starts again, and the activities and exercises a clip can be sent as — the team’s own list, filtered by what its plan covers and this server can analyse — with, per exercise, the camera views a send may carry and the recording guide (the coach upload wizard’s), in ?lang.
The Contribute level only: a View grant gets 403 contribute_required.
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.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Query Parameters
Section titled “Query Parameters”The guides’ language: en · ru · es (default: the grant’s).
Responses
Section titled “Responses”GET /api/portal/<client_id>/uploads/allowance/ (PortalUploadAllowance).
object
Set by the coach; 0 means uploads are off.
This calendar month’s (UTC) uploads whose analysis did not fail.
The day the count starts again.
What a clip can be sent as.
Per activity, the exercises it can be sent as (contract change 8); an empty list offers the activity’s default analysis (exercise: "").
object
Activity → exercise → the camera views (side, front, back) the analysis takes — the values camera_view may carry on the send; one view: show no picker. The default analysis is keyed "".
object
object
Activity → exercise → the recording guide in ?lang (else the grant’s language), the coach upload wizard’s: a dict of short texts keyed by part (the same shape as /api/exercises/’s guides_by_exercise). The default analysis is keyed "".
object
object
object
Activity → exercise → camera view → its guide, for the exercises with more than one view: what to show once the view is picked.
object
object
object
object
Examples
{ "monthly_cap": 4, "used_this_month": 1, "resets_on": "2026-12-01", "activities": [ "running" ], "exercises": { "running": [ "Treadmill", "Overground" ] }, "views_by_exercise": { "running": { "Treadmill": [ "side", "front", "back" ], "Overground": [ "side", "front", "back" ] } }, "guides_by_exercise": { "running": { "Treadmill": { "Camera": "Side or back view; phone on a tripod at waist height, kept still", "Duration": "15–30 s steady pace (skip warm-up)" }, "Overground": { "Camera": "Side view at hip height; the whole stride in frame" } } }, "guides_by_exercise_view": { "running": { "Treadmill": { "side": { "Camera": "Side view at waist height, kept still" }, "front": { "Camera": "Facing the runner at waist height" }, "back": { "Camera": "From behind at waist height" } } } }}object
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).
Example generated
{ "detail": "example"}object
access_ended, consent_required, or DRF’s message for a partner API key.
With access_ended: why the card no longer opens — revoked, team_plan or minor.
With consent_required: the version to accept.
With consent_required: the texts to show.
Examples
403 — a View grant
{ "detail": "contribute_required"}object
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).
Examples
404 — not a card of this account
{ "detail": "card_not_found"}object
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.
With throttled: whole seconds until the next request can pass.
Example generated
{ "detail": "example", "wait": 1}