Reserve a session_id and create a presigned upload URL
curl -X POST https://api.ai.aikynetix.app/api/sessions/upload-intent/ \ -H 'Authorization: Bearer aik_yourPartnerTokenHere' \ -H 'Content-Type: application/json' \ -d '{"filename":"clip.mp4","content_type":"video/mp4","activity":"running"}'import requestsr = requests.post( "https://api.ai.aikynetix.app/api/sessions/upload-intent/", headers={"Authorization": "Bearer aik_yourPartnerTokenHere"}, json={"filename": "clip.mp4", "content_type": "video/mp4", "activity": "running"}, timeout=30,)r.raise_for_status()intent = r.json()# Step 2: PUT the raw bytes to intent["url"] with intent["headers"].const r = await fetch("https://api.ai.aikynetix.app/api/sessions/upload-intent/", { method: "POST", headers: { Authorization: "Bearer aik_yourPartnerTokenHere", "Content-Type": "application/json" }, body: JSON.stringify({ filename: "clip.mp4", content_type: "video/mp4", activity: "running" }),});if (!r.ok) throw new Error(`HTTP ${r.status}`);const intent = await r.json();// Step 2: PUT raw bytes to intent.url with intent.headers.Step 1 of the upload-and-analyse workflow. Reserves a session UUID and mints a presigned PUT URL into teams/<team_id>/sessions/<yyyy>/<mm>/<session_id>.source.mp4. PUT the raw video bytes (MP4 / MOV / WebM, ≤200 MB) directly to that URL with the returned headers — no auth, expires in 15 minutes — then call POST /api/sessions/ passing the same session_id plus the returned public_url as video_url. Bypasses the API for the heavy upload so a flaky mobile network can retry the PUT without re-traversing your backend.
Auth: team-scoped — reachable with a partner aik_… API key.
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”Request body for POST /api/sessions/upload-intent/.
object
Original filename. Recorded for reference; never used as the storage key.
MIME type of the video (e.g. video/mp4). Replayed as the PUT Content-Type.
Activity the clip will be analysed as. Reserves the right storage prefix.
running- Runningwalking- Walkingjump- Vertical Jumpweightlifting- Weightliftingmobility- Mobility Assessmentworkspace_wellness- Workspace Wellnessagility- Agilityfencing- Fencingcycling- Cyclingtennis- Tennispadel- Padel Tennisbowling- Bowlingbaseball- Baseballfootball- Footballbadminton- Badmintoncricket- Cricketbasketball- Basketballscuba_diving- Scuba Divingice_hockey- Ice Hockeyamerican_football- American Footballfri- Falls Risk Indicator
MIME type of the optional posture-media upload — image or short (1-3 s) video showing the subject at their workstation. Only honoured when activity is workspace_wellness (gate is activity-level today; the WW activity carries a single exercise, Ergonomics Assessment, so the pair is equivalent — the first additional WW exercise will need this gate refined or it inherits a mandatory survey). Ignored for every other activity. When present and the activity matches, the response carries a second posture_media intent block alongside the primary video presign. Must be one of video/mp4, video/quicktime, image/jpeg, image/png, image/webp — anything else 400s. Damian’s Q11 from #303.
Examples
Running, treadmill clip
{ "filename": "treadmill_2026-04-29.mp4", "content_type": "video/mp4", "activity": "running"}Request body for POST /api/sessions/upload-intent/.
object
Original filename. Recorded for reference; never used as the storage key.
MIME type of the video (e.g. video/mp4). Replayed as the PUT Content-Type.
Activity the clip will be analysed as. Reserves the right storage prefix.
running- Runningwalking- Walkingjump- Vertical Jumpweightlifting- Weightliftingmobility- Mobility Assessmentworkspace_wellness- Workspace Wellnessagility- Agilityfencing- Fencingcycling- Cyclingtennis- Tennispadel- Padel Tennisbowling- Bowlingbaseball- Baseballfootball- Footballbadminton- Badmintoncricket- Cricketbasketball- Basketballscuba_diving- Scuba Divingice_hockey- Ice Hockeyamerican_football- American Footballfri- Falls Risk Indicator
MIME type of the optional posture-media upload — image or short (1-3 s) video showing the subject at their workstation. Only honoured when activity is workspace_wellness (gate is activity-level today; the WW activity carries a single exercise, Ergonomics Assessment, so the pair is equivalent — the first additional WW exercise will need this gate refined or it inherits a mandatory survey). Ignored for every other activity. When present and the activity matches, the response carries a second posture_media intent block alongside the primary video presign. Must be one of video/mp4, video/quicktime, image/jpeg, image/png, image/webp — anything else 400s. Damian’s Q11 from #303.
Request body for POST /api/sessions/upload-intent/.
object
Original filename. Recorded for reference; never used as the storage key.
MIME type of the video (e.g. video/mp4). Replayed as the PUT Content-Type.
Activity the clip will be analysed as. Reserves the right storage prefix.
running- Runningwalking- Walkingjump- Vertical Jumpweightlifting- Weightliftingmobility- Mobility Assessmentworkspace_wellness- Workspace Wellnessagility- Agilityfencing- Fencingcycling- Cyclingtennis- Tennispadel- Padel Tennisbowling- Bowlingbaseball- Baseballfootball- Footballbadminton- Badmintoncricket- Cricketbasketball- Basketballscuba_diving- Scuba Divingice_hockey- Ice Hockeyamerican_football- American Footballfri- Falls Risk Indicator
MIME type of the optional posture-media upload — image or short (1-3 s) video showing the subject at their workstation. Only honoured when activity is workspace_wellness (gate is activity-level today; the WW activity carries a single exercise, Ergonomics Assessment, so the pair is equivalent — the first additional WW exercise will need this gate refined or it inherits a mandatory survey). Ignored for every other activity. When present and the activity matches, the response carries a second posture_media intent block alongside the primary video presign. Must be one of video/mp4, video/quicktime, image/jpeg, image/png, image/webp — anything else 400s. Damian’s Q11 from #303.
Responses
Section titled “Responses”object
Reserved session UUID. Pass this back to POST /api/sessions/ as id.
Presigned PUT URL for the raw video bytes (expires in 15 min).
Always PUT.
Headers to replay verbatim on the PUT (e.g. Content-Type).
object
Storage key the upload lands at (team-scoped prefix).
Canonical URL of the uploaded object. Pass as video_url when creating the session.
Only present when activity is workspace_wellness AND the request supplied posture_media_content_type. Carries the second presign for the image-or-short-video upload that pairs with the ergonomics survey (Damian Q11 from #303). Independent of the primary video presign — uploadable in parallel.
object
Presigned PUT URL for the posture media bytes (expires in 15 min).
Always PUT.
Headers to replay verbatim on the PUT (e.g. Content-Type).
object
Storage key the upload lands at (team-scoped prefix).
Canonical URL of the uploaded posture media. Pass as workstation_assessment.posture_media.url when creating the workspace_wellness session.
Examples
Successful intent
{ "session_id": "5c836d7d-3301-49df-bfa0-9cff0550fd0e", "url": "https://s3.ai.aikynetix.app/aikynetix-media/teams/2648a781-8751-47c0-836d-2c0189792d71/sessions/2026/04/5c836d7d-3301-49df-bfa0-9cff0550fd0e.source.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=900&...", "method": "PUT", "headers": { "Content-Type": "video/mp4" }, "object_key": "teams/2648a781-8751-47c0-836d-2c0189792d71/sessions/2026/04/5c836d7d-3301-49df-bfa0-9cff0550fd0e.source.mp4", "public_url": "https://s3.ai.aikynetix.app/aikynetix-media/teams/2648a781-8751-47c0-836d-2c0189792d71/sessions/2026/04/5c836d7d-3301-49df-bfa0-9cff0550fd0e.source.mp4"}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).
Examplegenerated
{ "detail": "example"}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).
Examplegenerated
{ "detail": "example"}