For developers
Send rides to Velograph
In force from 10 October 2026 · Pro Cykling ApS
In short.
- If your app sends rides to Strava, it can send them to Velograph with the same code: change the host, the client id and the secret.
- OAuth 2.0 with the authorization code, as at Strava; PKCE is welcome and optional.
- Send the ride's original FIT file. It is read at once, so the first answer already says whether it worked.
- Your token can only add rides. Apart from the upload's status and the rider's name, it reads nothing back.
- Write to hello@velograph.ai for a client id and secret. Tell us your app's name, website and redirect addresses.
How a rider connects
The rider starts from your app's connections page, as for Strava. You send them to Velograph's consent page; they sign in, choose which of their riding profiles the rides go to (their own space, or a team they ride for), and come back to you with a code. Every finished ride then goes from your app to Velograph. Velograph analyses it like any other: ties it to the day's planned session, adds it to fitness and power curves, shares it with the coaches the rider chose, and counts it once when the same ride also arrives from a bike computer.
Addresses
| Authorize | GET https://velograph.ai/partners/oauth/authorize |
|---|---|
| Token | POST https://velograph.ai/partners/oauth/token |
| Revoke | POST https://velograph.ai/partners/oauth/revoke |
| API | https://velograph.ai/api/v3 |
1. Sign-in
Send the rider to the authorize address with:
| client_id | Your client id. |
|---|---|
| redirect_uri | One of the addresses you registered, exactly. |
| response_type | code |
| scope | activity:write (anything else asked for is ignored). |
| state | Your own value, returned unchanged. |
| code_challenge, code_challenge_method | Optional PKCE, S256 only. |
The rider comes back to redirect_uri?code=…&state=…, or ?error=access_denied. Trade the code within five minutes
at the token address, as a form (application/x-www-form-urlencoded), with client_id, client_secret
(or HTTP Basic), code, grant_type=authorization_code and the same redirect_uri; add
code_verifier if you sent a challenge. The answer:
{
"token_type": "Bearer",
"access_token": "vgat_…",
"expires_at": 1791640800,
"expires_in": 3600,
"refresh_token": "vgrt_…",
"scope": "activity:write",
"athlete": { "id": 3141592653589793, "id_str": "3141592653589793", "firstname": "Freja", "lastname": "Lund" }
}
Access tokens last an hour. Renew with grant_type=refresh_token and refresh_token: every renewal hands out a new
refresh token and retires the old one, so always keep the latest. A connection unused for 60 days ends. To disconnect, post
token to the revoke address with your client credentials.
2. Send a ride
POST https://velograph.ai/api/v3/uploads with Authorization: Bearer …, as multipart/form-data:
| file | The ride's original FIT file, up to 25 MB. |
|---|---|
| data_type | fit or fit.gz. TCX and GPX are not read: send the FIT file your app recorded. |
| external_id | Your id for the ride. Sending the same id again updates the ride rather than adding a second. |
| name, description | Optional; otherwise taken from the file. |
| trainer | 1 for a ride on an indoor trainer. |
curl -X POST https://velograph.ai/api/v3/uploads \ -H "Authorization: Bearer vgat_…" \ -F file=@ride.fit -F data_type=fit -F external_id=ride-8842 -F trainer=1
The answer is 201 Created with Strava's upload object:
{ "id": 1042, "id_str": "1042", "external_id": "ride-8842", "error": null,
"status": "Your activity is ready.", "activity_id": 1042 }
A file that cannot be read comes back with "status": "There was an error processing your activity." and the reason in
error. GET https://velograph.ai/api/v3/uploads/{id} answers the same object again, for code that waits for it.
GET https://velograph.ai/api/v3/athlete names the rider the token is for.
Limits and errors
- 100 requests per 15 minutes per token; past that,
429 Too Many Requests. - A token that has ended or was never valid gets
401with{"message": "Authorization Error", "errors": [ … ]}. - A missing file or data type gets
400naming the field.
The rider's data
The rides are the rider's. Velograph keeps them under its privacy policy, shows them only to the people the rider chose, and the rider can disconnect your app from their Velograph profile at any time. Velograph does not send anything back to your app beyond the answers above.
Coming next
Planned sessions the other way, so a rider's coming week appears in your app: a list for a date range and each session as a ZWO or FIT workout file. Tell us if your app would use it.