Documentation
Sweliv developer API
Authenticate your users with “Sign in with Sweliv” and pull in their sports activities. A read-only API, protected by OAuth 2.0 (Authorization Code + PKCE).
Introduction
The Sweliv API lets your app import a user’s activities, with their explicit consent. It is a standard OAuth 2.0 flow, the same one behind “Sign in with Strava / Google”.
- Flow: Authorization Code + PKCE (
S256method, required). - Scope:
activities:read(read-only). - Tokens: access token (1 h) + refresh token (60 days, rotating).
- API base URL:
https://api.sweliv.com
Before you start
Ask the Sweliv team for your credentials (support@sweliv.com), giving us the name of your app and your callback URL(s). You will receive:
| client_id | Public identifier for your app (e.g. swlv_a1b2c3…). |
| client_secret | Secret, shown only once. Keep it server-side, never in the browser. |
The callback URL (redirect_uri)
You are free to choose its path, for example https://ton-app.com/auth/sweliv/callback. It is a route you write in your app to pick up the code Sweliv sends back:
https://ton-app.com/auth/sweliv/callback?code=ABC123&state=xyzThree things to remember:
- You define it, then you send it to us so we can register it. We do not invent it for you.
- Exact match required: the
redirect_urisent on every request must be byte-for-byte the one we registered (protection against interception). - You can register several of them (e.g. one for production, one for testing:
http://localhost:3000/callback).
The flow at a glance
- 1The user taps “Import my Sweliv activities” in your app.
- 2You redirect them to the Sweliv consent screen.
- 3They sign in (Google / Apple / email) and authorize your app.
- 4Sweliv sends them back to your callback with a single-use code.
- 5Your server exchanges that code for an access token.
- 6You call the API with that token and import their activities.
1 · Authorization (PKCE + redirect)
Generate a random code_verifier, compute its code_challenge = base64url(sha256(verifier)), keep the verifier in the session, then redirect the user:
// Node.js
import crypto from 'node:crypto';
const verifier = crypto.randomBytes(32).toString('base64url');
const challenge = crypto.createHash('sha256')
.update(verifier).digest('base64url');
// → stocke `verifier` en session (requis à l'étape 2)GEThttps://sweliv.com/oauth/authorize
https://sweliv.com/oauth/authorize
?response_type=code
&client_id=swlv_xxx
&redirect_uri=https://ton-app.com/auth/sweliv/callback
&scope=activities:read
&state=<aléatoire-anti-CSRF>
&code_challenge=<base64url(sha256(verifier))>
&code_challenge_method=S256After authorization, Sweliv redirects to your callback with ?code=…&state=…. Check that the state matches the one you sent.
2 · Exchanging the code for a token
In your callback handler, server-side:
POSThttps://api.sweliv.com/oauth/token
POST /oauth/token (Content-Type: application/json)
{
"grant_type": "authorization_code",
"client_id": "swlv_xxx",
"client_secret": "<si app confidentielle>",
"code": "ABC123",
"redirect_uri": "https://ton-app.com/auth/sweliv/callback",
"code_verifier": "<le verifier de l'étape 1>"
}Response:
{
"access_token": "...",
"refresh_token": "...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "activities:read"
}3 · Calling the API
Pass the access token in the Authorization: Bearer <token> header. The data is automatically limited to the user who authorized you.
GEThttps://api.sweliv.com/api/v1/activities
GET /api/v1/activities?limit=30&cursor=<id>
Authorization: Bearer <access_token>
{
"data": [
{
"id": "ckxy...",
"sport": "RUN",
"status": "COMPLETED",
"startedAt": "2026-05-30T07:12:00.000Z",
"endedAt": "2026-05-30T07:58:21.000Z",
"distanceMeters": 10240,
"durationSeconds": 2781,
"title": "Tempo run",
"description": null,
"group": { "id": "ckg...", "name": "Run Club Paris" }
}
],
"nextCursor": "ckxw..."
}Cursor pagination: pass nextCursor back in ?cursor=. null means the end of the list. limit goes from 1 to 100 (30 by default).
4 · Refreshing the token
When the access token expires (401), exchange the refresh token. It is rotating: every refresh returns a new one and invalidates the previous one. Always store the latest one you received.
POST /oauth/token (Content-Type: application/json)
{
"grant_type": "refresh_token",
"client_id": "swlv_xxx",
"client_secret": "<si app confidentielle>",
"refresh_token": "<le refresh token>"
}Endpoint reference
| GET /oauth/authorize | Consent screen (on sweliv.com). |
| POST /oauth/token | Code exchange + refresh (api.sweliv.com). |
| GET /api/v1/activities | Paginated list of the user’s activities. |
| GET /api/v1/activities/:id | A single activity (same shape). |
The Activity object
| id | Unique identifier. |
| sport | RUN, CYCLING, GYM, TENNIS, PADEL, SWIMMING, SWIMMING_POOL, TRIATHLON. |
| status | Always COMPLETED (ongoing activities are not exposed). |
| startedAt | Start (ISO 8601, UTC). |
| endedAt | End (ISO 8601), or null. |
| distanceMeters | Distance in metres (integer). |
| durationSeconds | Duration in seconds (integer). |
| title | Title set by the user, or null. |
| description | Free-text description, or null. |
| group | { id, name } of the linked group, or null. |
Scopes
| activities:read | Read the list and the detail of activities. (The only scope available today.) |
Errors & limits
| 429 | Rate limit: 120 req / min / token. Retry after the delay we return. |
| 401 | Token missing, expired or revoked. Refresh it. |
| 403 | Insufficient scope for this endpoint. |
| 404 | Activity does not exist, or belongs to another user (we do not tell the two apart, for privacy). |
| 400 | Invalid request (PKCE, expired or reused code, redirect_uri mismatch…). |
FAQ
What is the callback URL?
The page in your app that Sweliv sends the user back to after authorization, with the code in the URL. You choose its path, and you send it to us so we can register it. See the “The callback URL” section.
Can my Google / Apple users sign in?
Yes. The consent screen handles Google, Apple and email/password, which covers every Sweliv sign-up method.
Is the client_secret required?
For an app with a backend (confidential), yes. For a SPA or a mobile app (public), no: PKCE alone is enough. Tell us which one you are at registration.
Can I write or create activities through the API?
No, the API is read-only for now (scope activities:read only).
A question? support@sweliv.com