curl --request POST \
--url https://api.uplift.ai/v1/data/export \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"startTime": 123,
"endTime": 123,
"athletes": [
"<string>"
],
"metrics": [
"<string>"
],
"row_filter_column": "<string>"
}
'import requests
url = "https://api.uplift.ai/v1/data/export"
payload = {
"startTime": 123,
"endTime": 123,
"athletes": ["<string>"],
"metrics": ["<string>"],
"row_filter_column": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
startTime: 123,
endTime: 123,
athletes: ['<string>'],
metrics: ['<string>'],
row_filter_column: '<string>'
})
};
fetch('https://api.uplift.ai/v1/data/export', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.uplift.ai/v1/data/export",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'startTime' => 123,
'endTime' => 123,
'athletes' => [
'<string>'
],
'metrics' => [
'<string>'
],
'row_filter_column' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.uplift.ai/v1/data/export"
payload := strings.NewReader("{\n \"startTime\": 123,\n \"endTime\": 123,\n \"athletes\": [\n \"<string>\"\n ],\n \"metrics\": [\n \"<string>\"\n ],\n \"row_filter_column\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.uplift.ai/v1/data/export")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"startTime\": 123,\n \"endTime\": 123,\n \"athletes\": [\n \"<string>\"\n ],\n \"metrics\": [\n \"<string>\"\n ],\n \"row_filter_column\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.uplift.ai/v1/data/export")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"startTime\": 123,\n \"endTime\": 123,\n \"athletes\": [\n \"<string>\"\n ],\n \"metrics\": [\n \"<string>\"\n ],\n \"row_filter_column\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"jobId": "<string>"
}{
"error": "BadRequest",
"message": "The request parameters are invalid. Please review the request and try again."
}{
"error": "Unauthorized",
"message": "Bearer token is missing or invalid."
}{
"error": "Forbidden",
"message": "You do not have permission to access this resource."
}{
"error": "PayloadTooLarge",
"message": "The requested export is too large. Narrow the date range or request fewer athletes."
}{
"error": "TooManyRequests",
"message": "The rate limit has been exceeded. Please wait and try again later."
}{
"error": "InternalServerError",
"message": "An unexpected error occurred on the server. Please try again later."
}Create Export Job
Initiates an asynchronous data export process and returns a job ID that clients can use to poll for query results.
curl --request POST \
--url https://api.uplift.ai/v1/data/export \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"startTime": 123,
"endTime": 123,
"athletes": [
"<string>"
],
"metrics": [
"<string>"
],
"row_filter_column": "<string>"
}
'import requests
url = "https://api.uplift.ai/v1/data/export"
payload = {
"startTime": 123,
"endTime": 123,
"athletes": ["<string>"],
"metrics": ["<string>"],
"row_filter_column": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
startTime: 123,
endTime: 123,
athletes: ['<string>'],
metrics: ['<string>'],
row_filter_column: '<string>'
})
};
fetch('https://api.uplift.ai/v1/data/export', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.uplift.ai/v1/data/export",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'startTime' => 123,
'endTime' => 123,
'athletes' => [
'<string>'
],
'metrics' => [
'<string>'
],
'row_filter_column' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.uplift.ai/v1/data/export"
payload := strings.NewReader("{\n \"startTime\": 123,\n \"endTime\": 123,\n \"athletes\": [\n \"<string>\"\n ],\n \"metrics\": [\n \"<string>\"\n ],\n \"row_filter_column\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.uplift.ai/v1/data/export")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"startTime\": 123,\n \"endTime\": 123,\n \"athletes\": [\n \"<string>\"\n ],\n \"metrics\": [\n \"<string>\"\n ],\n \"row_filter_column\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.uplift.ai/v1/data/export")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"startTime\": 123,\n \"endTime\": 123,\n \"athletes\": [\n \"<string>\"\n ],\n \"metrics\": [\n \"<string>\"\n ],\n \"row_filter_column\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"jobId": "<string>"
}{
"error": "BadRequest",
"message": "The request parameters are invalid. Please review the request and try again."
}{
"error": "Unauthorized",
"message": "Bearer token is missing or invalid."
}{
"error": "Forbidden",
"message": "You do not have permission to access this resource."
}{
"error": "PayloadTooLarge",
"message": "The requested export is too large. Narrow the date range or request fewer athletes."
}{
"error": "TooManyRequests",
"message": "The rate limit has been exceeded. Please wait and try again later."
}{
"error": "InternalServerError",
"message": "An unexpected error occurred on the server. Please try again later."
}Access
The data export endpoints require your organization to have developer API access enabled. If it is not enabled, every export request returns403 Forbidden. Contact
our sales team to enable API access for your organization.
Data access level (Summary vs Full)
Each organization has a data access level that controls the granularity of the exported data. It is set at the account level (contact sales) — it is not a request parameter, and it is not returned in the response.Full
Returns the complete dataset: every metric, the per-frame kinematic time series, and 3D keypoints.Summary
Returns a single discrete row per capture — summary metrics only. The per-frame time series and 3D keypoints are not included. Because a summary export is already one row per capture, the following requests are rejected up front with a400 on
POST /data/export:
| Request on the summary level | Result |
|---|---|
row_filter_column provided | 400 — not applicable; a summary export is already one row per capture. |
a metrics value that exists only in the full dataset | 400 — that metric is only available with full data access. |
an activity/movement offered only at the full level | 400 — not available on the summary level. (A genuinely unknown pair still returns the standard invalid activity/movement 400.) |
Export size limits
| Limit | Result when exceeded |
|---|---|
athletes: at most 100 athlete IDs per request | 400 — the standard invalid request response. |
metrics: at most 300 metrics per request | 400 — the standard invalid request response. |
| Estimated result size above the export size limit | 413 — no job is created. |
POST /data/export returns 413:
{
"error": "PayloadTooLarge",
"message": "The requested export is too large. Narrow the date range or request fewer athletes."
}
Valid activity-movement pairs
Only the followingactivity and movement pairs are accepted. Any other pair returns a 400 error.
| Activity | Valid movements |
|---|---|
| agility | cutting, five_ten_five |
| baseball | hitting, pitching |
| basketball | free_throw, jump_shot, layup |
| gait | running, walking |
| golf | swing |
| jump | broad, countermovement, drop_vertical, single_leg, single_leg_broad, squat |
| lunge | forward |
| other | other |
| range_of_motion | ankle_flexion, cervical_flexion_extension, cervical_rotation, sfma_shoulder_extension, sfma_shoulder_flexion, shoulder_9090, shoulder_flexion, t_spine_rotation |
| softball | hitting |
| squat | body_weight, overhead, sfma_squat, single_leg |
| stability | plank, push_up, rotary, sfma_back_bend, sfma_toe_touch, single_leg_stance, static_stance, y_balance_lower_quarter, y_balance_upper_quarter |
| track_and_field | discus, hammer_throw, high_jump, shot_put |
| tennis | backhand, forehand, overhand_serve, underhand_serve |
400. Contact sales if you need summary access to a pair
that is currently full-only.Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Specifies the type of activity for the export.
agility, baseball, basketball, gait, golf, jump, lunge, other, range_of_motion, softball, squat, stability, track_and_field, tennis Further filters the export based on specific movement type.
cutting, hitting, pitching, free_throw, jump_shot, layup, running, walking, swing, broad, countermovement, drop_vertical, single_leg, single_leg_broad, squat, forward, other, static_stance, ankle_flexion, cervical_flexion_extension, cervical_rotation, sfma_shoulder_extension, sfma_shoulder_flexion, shoulder_9090, shoulder_flexion, t_spine_rotation, body_weight, overhead, sfma_squat, plank, push_up, rotary, sfma_back_bend, sfma_toe_touch, single_leg_stance, y_balance_lower_quarter, y_balance_upper_quarter, hammer_throw, high_jump, shot_put, five_ten_five, discus, backhand, forehand, overhand_serve, underhand_serve Specifies the start of the time range for data retrieval in epoch time (UTC). Defaults to 24 hours prior to reduce the volume of data exported.
Specifies the end of the time range for data retrieval in epoch time (UTC). Defaults to the current time to provide up-to-date information.
The list of athlete IDs to identify athlete data to be included in the export job. At most 100 athlete IDs per request; more returns a 400.
100Determines which date field ('last_modified' or 'capture_time') should be used for time-based filtering. Defaults to 'last_modified'.
last_modified, capture_time The list of metrics to include in the export job. At most 300 metrics per request; more returns a 400.
Read more about Filtering Metrics for usage examples.
300Control the row of the session to be exported. Only the row with the specified column value equal to 0 will be exported.
Read more about Filtering Metrics for usage examples.
Response
Export request successfully created. Returns a job ID to track the export status.
The unique identifier for the export job. Use this ID to poll for export status and retrieve results.