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 (S256 method, 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_idPublic identifier for your app (e.g. swlv_a1b2c3…).
client_secretSecret, shown only once. Keep it server-side, never in the browser.

The callback URL (redirect_uri)

It is the page in YOUR app that Sweliv sends the user back to once they have clicked “Authorize”.

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=xyz

Three 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_uri sent 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

  1. 1The user taps “Import my Sweliv activities” in your app.
  2. 2You redirect them to the Sweliv consent screen.
  3. 3They sign in (Google / Apple / email) and authorize your app.
  4. 4Sweliv sends them back to your callback with a single-use code.
  5. 5Your server exchanges that code for an access token.
  6. 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=S256

After 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/authorizeConsent screen (on sweliv.com).
POST /oauth/tokenCode exchange + refresh (api.sweliv.com).
GET /api/v1/activitiesPaginated list of the user’s activities.
GET /api/v1/activities/:idA single activity (same shape).

The Activity object

idUnique identifier.
sportRUN, CYCLING, GYM, TENNIS, PADEL, SWIMMING, SWIMMING_POOL, TRIATHLON.
statusAlways COMPLETED (ongoing activities are not exposed).
startedAtStart (ISO 8601, UTC).
endedAtEnd (ISO 8601), or null.
distanceMetersDistance in metres (integer).
durationSecondsDuration in seconds (integer).
titleTitle set by the user, or null.
descriptionFree-text description, or null.
group{ id, name } of the linked group, or null.

Scopes

activities:readRead the list and the detail of activities. (The only scope available today.)

Errors & limits

429Rate limit: 120 req / min / token. Retry after the delay we return.
401Token missing, expired or revoked. Refresh it.
403Insufficient scope for this endpoint.
404Activity does not exist, or belongs to another user (we do not tell the two apart, for privacy).
400Invalid 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