Workouts

GET /api/workouts

Get workouts for the authenticated user.

Scope: workouts:read

Example requests:

  • without parameters:

GET /api/workouts/ HTTP/1.1
  • with some query parameters:

GET /api/workouts?from=2019-07-02&to=2019-07-31&sport_id=1  HTTP/1.1

Example responses:

  • returning at least one workout:

HTTP/1.1 200 OK
Content-Type: application/json

  {
    "data": {
      "workouts": [
        {
          "ascent": null,
          "ave_speed": 10.0,
          "bounds": [],
          "creation_date": "Sun, 14 Jul 2019 13:51:01 GMT",
          "descent": null,
          "distance": 10.0,
          "duration": "0:17:04",
          "equipments": [],
          "id": "kjxavSTUrJvoAh2wvCeGEF",
          "map": null,
          "max_alt": null,
          "max_speed": 10.0,
          "min_alt": null,
          "modification_date": null,
          "moving": "0:17:04",
          "next_workout": 3,
          "notes": null,
          "pauses": null,
          "previous_workout": null,
          "records": [
            {
              "id": 4,
              "record_type": "MS",
              "sport_id": 1,
              "user": "admin",
              "value": 10.0,
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF"
            },
            {
              "id": 13,
              "record_type": "HA",
              "sport_id": 1,
              "user": "Sam",
              "value": 43.97,
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            },
            {
              "id": 3,
              "record_type": "LD",
              "sport_id": 1,
              "user": "admin",
              "value": "0:17:04",
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF"
            },
            {
              "id": 2,
              "record_type": "FD",
              "sport_id": 1,
              "user": "admin",
              "value": 10.0,
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF"
            },
            {
              "id": 1,
              "record_type": "AS",
              "sport_id": 1,
              "user": "admin",
              "value": 10.0,
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF"
            }
          ],
          "segments": [],
          "sport_id": 1,
          "title": null,
          "user": "admin",
          "weather_end": null,
          "weather_start": null,
          "with_gpx": false,
          "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT"
        }
      ]
    },
    "status": "success"
  }
  • returning no workouts

HTTP/1.1 200 OK
Content-Type: application/json

  {
      "data": {
          "workouts": []
      },
      "status": "success"
  }
Query Parameters:
  • page (integer) – page if using pagination (default: 1)

  • per_page (integer) – number of workouts per page (default: 5, max: 100)

  • sport_id (integer) – sport id

  • title (string) – any part (or all) of the workout title; title matching is case-insensitive

  • from (string) – start date (format: %Y-%m-%d)

  • to (string) – end date (format: %Y-%m-%d)

  • distance_from (float) – minimal distance

  • distance_to (float) – maximal distance

  • duration_from (string) – minimal duration (format: %H:%M)

  • duration_to (string) – maximal distance (format: %H:%M)

  • ave_speed_from (float) – minimal average speed

  • ave_speed_to (float) – maximal average speed

  • max_speed_from (float) – minimal max. speed

  • max_speed_to (float) – maximal max. speed

  • order (string) – sorting order: asc, desc (default: desc)

  • order_by (string) – sorting criteria: ave_speed, distance, duration, workout_date (default: workout_date)

  • equipment_id (string) – equipment id (if ‘none’, only workouts without equipments will be returned)

  • notes (string) – any part (or all) of the workout notes, notes matching is case-insensitive

Request Headers:
Status Codes:
GET /api/workouts/(string: workout_short_id)

Get a workout.

Scope: workouts:read

Example request:

GET /api/workouts/kjxavSTUrJvoAh2wvCeGEF HTTP/1.1

Example responses:

  • success:

HTTP/1.1 200 OK
Content-Type: application/json

  {
    "data": {
      "workouts": [
        {
          "ascent": null,
          "ave_speed": 16,
          "bounds": [],
          "creation_date": "Sun, 14 Jul 2019 18:57:14 GMT",
          "descent": null,
          "distance": 12,
          "duration": "0:45:00",
          "equipments": [],
          "id": "kjxavSTUrJvoAh2wvCeGEF",
          "map": null,
          "max_alt": null,
          "max_speed": 16,
          "min_alt": null,
          "modification_date": "Sun, 14 Jul 2019 18:57:22 GMT",
          "moving": "0:45:00",
          "next_workout": 4,
          "notes": "workout without gpx",
          "pauses": null,
          "previous_workout": 3,
          "records": [],
          "segments": [],
          "sport_id": 1,
          "title": "biking on sunday morning",
          "user": "admin",
          "weather_end": null,
          "weather_start": null,
          "with_gpx": false,
          "workout_date": "Sun, 07 Jul 2019 07:00:00 GMT"
        }
      ]
    },
    "status": "success"
  }
  • workout not found:

HTTP/1.1 404 NOT FOUND
Content-Type: application/json

  {
    "data": {
      "workouts": []
    },
    "status": "not found"
  }
Parameters:
  • workout_short_id (string) – workout short id

Request Headers:
Status Codes:
GET /api/workouts/(string: workout_short_id)/gpx

Get gpx file for a workout displayed on map with Leaflet.

Scope: workouts:read

Example request:

GET /api/workouts/kjxavSTUrJvoAh2wvCeGEF/gpx HTTP/1.1
Content-Type: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": {
    "gpx": "gpx file content"
  },
  "message": "",
  "status": "success"
}
Parameters:
  • workout_short_id (string) – workout short id

Request Headers:
Status Codes:
GET /api/workouts/(string: workout_short_id)/chart_data

Get chart data from a workout gpx file, to display it with Chart.js.

Scope: workouts:read

Example request:

GET /api/workouts/kjxavSTUrJvoAh2wvCeGEF/chart HTTP/1.1
Content-Type: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": {
    "chart_data": [
      {
        "distance": 0,
        "duration": 0,
        "elevation": 279.4,
        "latitude": 51.5078118,
        "longitude": -0.1232004,
        "speed": 8.63,
        "time": "Fri, 14 Jul 2017 13:44:03 GMT"
      },
      {
        "distance": 7.5,
        "duration": 7380,
        "elevation": 280,
        "latitude": 51.5079733,
        "longitude": -0.1234538,
        "speed": 6.39,
        "time": "Fri, 14 Jul 2017 15:47:03 GMT"
      }
    ]
  },
  "message": "",
  "status": "success"
}
Parameters:
  • workout_short_id (string) – workout short id

Request Headers:
Status Codes:
GET /api/workouts/(string: workout_short_id)/chart_data/segment/(int: segment_id)

Get chart data from a workout gpx file, to display it with Chart.js.

Scope: workouts:read

Example request:

GET /api/workouts/kjxavSTUrJvoAh2wvCeGEF/chart/segment/0 HTTP/1.1
Content-Type: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": {
    "chart_data": [
      {
        "distance": 0,
        "duration": 0,
        "elevation": 279.4,
        "latitude": 51.5078118,
        "longitude": -0.1232004,
        "speed": 8.63,
        "time": "Fri, 14 Jul 2017 13:44:03 GMT"
      },
      {
        "distance": 7.5,
        "duration": 7380,
        "elevation": 280,
        "latitude": 51.5079733,
        "longitude": -0.1234538,
        "speed": 6.39,
        "time": "Fri, 14 Jul 2017 15:47:03 GMT"
      }
    ]
  },
  "message": "",
  "status": "success"
}
Parameters:
  • workout_short_id (string) – workout short id

  • segment_id (integer) – segment id

Request Headers:
Status Codes:
GET /api/workouts/(string: workout_short_id)/gpx/segment/(int: segment_id)

Get gpx file for a workout segment displayed on map with Leaflet.

Scope: workouts:read

Example request:

GET /api/workouts/kjxavSTUrJvoAh2wvCeGEF/gpx/segment/0 HTTP/1.1
Content-Type: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": {
    "gpx": "gpx file content"
  },
  "message": "",
  "status": "success"
}
Parameters:
  • workout_short_id (string) – workout short id

  • segment_id (integer) – segment id

Request Headers:
Status Codes:
GET /api/workouts/map/(map_id)

Get map image for workouts with gpx.

Example request:

GET /api/workouts/map/fa33f4d996844a5c73ecd1ae24456ab8?1563529507772
  HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: image/png
Parameters:
  • map_id (string) – workout map id

Status Codes:
GET /api/workouts/map_tile/(s)/(z)/(x)/(y).png

Get map tile from tile server.

Example request:

GET /api/workouts/map_tile/c/13/4109/2930.png HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: image/png
Parameters:
  • s (string) – subdomain

  • z (string) – zoom

  • x (string) – index of the tile along the map’s x axis

  • y (string) – index of the tile along the map’s y axis

Status codes are status codes returned by tile server

GET /api/workouts/(string: workout_short_id)/gpx/download

Download gpx file.

Scope: workouts:read

Example request:

GET /api/workouts/kjxavSTUrJvoAh2wvCeGEF/gpx/download HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: application/gpx+xml
Parameters:
  • workout_short_id (string) – workout short id

Status Codes:
  • 200 OKsuccess

  • 401 Unauthorized

    • provide a valid auth token

    • signature expired, please log in again

    • invalid token, please log in again

  • 404 Not Found

    • workout not found

    • no gpx file for workout

POST /api/workouts

Post a workout with a gpx file.

Scope: workouts:write

Example request:

POST /api/workouts/ HTTP/1.1
Content-Type: multipart/form-data

Example response:

HTTP/1.1 201 CREATED
Content-Type: application/json

 {
    "data": {
      "workouts": [
        {
          "ascent": null,
          "ave_speed": 10.0,
          "bounds": [],
          "creation_date": "Sun, 14 Jul 2019 13:51:01 GMT",
          "descent": null,
          "distance": 10.0,
          "duration": "0:17:04",
          "equipments": [],
          "id": "kjxavSTUrJvoAh2wvCeGEF",
          "map": null,
          "max_alt": null,
          "max_speed": 10.0,
          "min_alt": null,
          "modification_date": null,
          "moving": "0:17:04",
          "next_workout": 3,
          "notes": null,
          "pauses": null,
          "previous_workout": null,
          "records": [
            {
              "id": 4,
              "record_type": "MS",
              "sport_id": 1,
              "user": "admin",
              "value": 10.,
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF"
            },
            {
              "id": 3,
              "record_type": "LD",
              "sport_id": 1,
              "user": "admin",
              "value": "0:17:04",
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF",
            },
            {
              "id": 2,
              "record_type": "FD",
              "sport_id": 1,
              "user": "admin",
              "value": 10.0,
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF"
            },
            {
              "id": 1,
              "record_type": "AS",
              "sport_id": 1,
              "user": "admin",
              "value": 10.0,
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF"
            }
          ],
          "segments": [],
          "sport_id": 1,
          "title": null,
          "user": "admin",
          "weather_end": null,
          "weather_start": null,
          "with_gpx": false,
          "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT"
        }
      ]
    },
    "status": "success"
  }
Form Parameters:
  • file – gpx file (allowed extensions: .gpx, .zip)

  • data

    sport id, equipment id and notes (example: {"sport_id": 1, "notes": "", "equipment_ids": []}). Double quotes in notes must be escaped.

    For equipment_ids, the id of the equipment to associate with this workout. Note: for now only one equipment can be associated. If not provided and default equipment exists for sport, default equipment will be associated.

    Notes and equipment ids are not mandatory.

Request Headers:
Status Codes:
  • 201 Created – workout created

  • 400 Bad Request

    • invalid payload

    • no file part

    • no selected file

    • file extension not allowed

    • equipment_ids must be an array of strings

    • only one equipment can be added

    • equipment with id <equipment_id> does not exist

    • invalid equipment id <equipment_id> for sport

    • equipment with id <equipment_id> is inactive

  • 401 Unauthorized

    • provide a valid auth token

    • signature expired, please log in again

    • invalid token, please log in again

  • 413 Request Entity Too Largeerror during picture update: file size exceeds 1.0MB

  • 500 Internal Server Errorerror, please try again or contact the administrator

POST /api/workouts/no_gpx

Post a workout without gpx file.

Scope: workouts:write

Example request:

POST /api/workouts/no_gpx HTTP/1.1
Content-Type: application/json

Example response:

HTTP/1.1 201 CREATED
Content-Type: application/json

 {
    "data": {
      "workouts": [
        {
          "ascent": null,
          "ave_speed": 10.0,
          "bounds": [],
          "creation_date": "Sun, 14 Jul 2019 13:51:01 GMT",
          "descent": null,
          "distance": 10.0,
          "duration": "0:17:04",
          "equipments": [],
          "map": null,
          "max_alt": null,
          "max_speed": 10.0,
          "min_alt": null,
          "modification_date": null,
          "moving": "0:17:04",
          "next_workout": 3,
          "notes": null,
          "pauses": null,
          "previous_workout": null,
          "records": [
            {
              "id": 4,
              "record_type": "MS",
              "sport_id": 1,
              "user": "admin",
              "value": 10.,
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF"
            },
            {
              "id": 3,
              "record_type": "LD",
              "sport_id": 1,
              "user": "admin",
              "value": "0:17:04",
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF"
            },
            {
              "id": 2,
              "record_type": "FD",
              "sport_id": 1,
              "user": "admin",
              "value": 10.0,
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF"
            },
            {
              "id": 1,
              "record_type": "AS",
              "sport_id": 1,
              "user": "admin",
              "value": 10.0,
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF"
            }
          ],
          "segments": [],
          "sport_id": 1,
          "title": null,
          "user": "admin",
          "uuid": "kjxavSTUrJvoAh2wvCeGEF"
          "weather_end": null,
          "weather_start": null,
          "with_gpx": false,
          "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT"
        }
      ]
    },
    "status": "success"
  }
Request JSON Object:
  • ascent (float) – workout ascent (not mandatory, must be provided with descent)

  • descent (float) – workout descent (not mandatory, must be provided with ascent)

  • distance (float) – workout distance in km

  • duration (integer) – workout duration in seconds

  • equipment_ids (array of strings) – the id of the equipment to associate with this workout. Note: for now only one equipment can be associated. If not provided and default equipment exists for sport, default equipment will be associated.

  • notes (string) – notes (not mandatory)

  • sport_id (integer) – workout sport id

  • title (string) – workout title (not mandatory)

  • workout_date (string) – workout date, in user timezone (format: %Y-%m-%d %H:%M)

Request Headers:
Status Codes:
  • 201 Created – workout created

  • 400 Bad Request

    • invalid payload

    • equipment_ids must be an array of strings

    • only one equipment can be added

    • equipment with id <equipment_id> does not exist

    • invalid equipment id <equipment_id> for sport

    • equipment with id <equipment_id> is inactive

  • 401 Unauthorized

    • provide a valid auth token

    • signature expired, please log in again

    • invalid token, please log in again

  • 500 Internal Server Errorerror, please try again or contact the administrator

PATCH /api/workouts/(string: workout_short_id)

Update a workout.

Scope: workouts:write

Example request:

PATCH /api/workouts/1 HTTP/1.1
Content-Type: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

 {
    "data": {
      "workouts": [
        {
          "ascent": null,
          "ave_speed": 10.0,
          "bounds": [],
          "creation_date": "Sun, 14 Jul 2019 13:51:01 GMT",
          "descent": null,
          "distance": 10.0,
          "duration": "0:17:04",
          "equipments": [],
          "map": null,
          "max_alt": null,
          "max_speed": 10.0,
          "min_alt": null,
          "modification_date": null,
          "moving": "0:17:04",
          "next_workout": 3,
          "notes": null,
          "pauses": null,
          "previous_workout": null,
          "records": [
            {
              "id": 4,
              "record_type": "MS",
              "sport_id": 1,
              "user": "admin",
              "value": 10.0,
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF"
            },
            {
              "id": 3,
              "record_type": "LD",
              "sport_id": 1,
              "user": "admin",
              "value": "0:17:04",
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF"
            },
            {
              "id": 2,
              "record_type": "FD",
              "sport_id": 1,
              "user": "admin",
              "value": 10.0,
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF",
            },
            {
              "id": 1,
              "record_type": "AS",
              "sport_id": 1,
              "user": "admin",
              "value": 10.0,
              "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT",
              "workout_id": "kjxavSTUrJvoAh2wvCeGEF",
            }
          ],
          "segments": [],
          "sport_id": 1,
          "title": null,
          "user": "admin",
          "uuid": "kjxavSTUrJvoAh2wvCeGEF"
          "weather_end": null,
          "weather_start": null,
          "with_gpx": false,
          "workout_date": "Mon, 01 Jan 2018 00:00:00 GMT"
        }
      ]
    },
    "status": "success"
  }
Parameters:
  • workout_short_id (string) – workout short id

Request JSON Object:
  • ascent (float) – workout ascent (only for workout without gpx, must be provided with descent)

  • descent (float) – workout descent (only for workout without gpx, must be provided with ascent)

  • distance (float) – workout distance in km (only for workout without gpx)

  • duration (integer) – workout duration in seconds (only for workout without gpx)

  • notes (string) – notes

  • sport_id (integer) – workout sport id

  • title (string) – workout title

  • equipment_ids (array of strings) – the id of the equipment to associate with this workout (any existing equipment for this workout will be replaced). Note: for now only one equipment can be associated. If an empty array, equipment for this workout will be removed.

  • workout_date (string) – workout date in user timezone (format: %Y-%m-%d %H:%M) (only for workout without gpx)

Request Headers:
Status Codes:
  • 200 OK – workout updated

  • 400 Bad Request

    • invalid payload

    • equipment_ids must be an array of strings

    • only one equipment can be added

    • equipment with id <equipment_id> does not exist

    • invalid equipment id <equipment_id> for sport

    • equipment with id <equipment_id> is inactive

  • 401 Unauthorized

    • provide a valid auth token

    • signature expired, please log in again

    • invalid token, please log in again

  • 404 Not Foundworkout not found

  • 500 Internal Server Errorerror, please try again or contact the administrator

DELETE /api/workouts/(string: workout_short_id)

Delete a workout.

Scope: workouts:write

Example request:

DELETE /api/workouts/kjxavSTUrJvoAh2wvCeGEF HTTP/1.1
Content-Type: application/json

Example response:

HTTP/1.1 204 NO CONTENT
Content-Type: application/json
Parameters:
  • workout_short_id (string) – workout short id

Request Headers:
Status Codes: