# 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",
                "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

    - 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 (default: `desc`)

  Request Headers:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 200 OK – success

    - 401 Unauthorized –

      - provide a valid auth token

      - signature expired, please log in again

      - invalid token, please log in again

    - 500 Internal Server Error –

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",
                "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:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 200 OK – success

    - 401 Unauthorized –

      - provide a valid auth token

      - signature expired, please log in again

      - invalid token, please log in again

    - 403 Forbidden – you do not have permissions

    - 404 Not Found – workout not found

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:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 200 OK – success

    - 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 this workout

    - 500 Internal Server Error –

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:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 200 OK – success

    - 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 this workout

    - 500 Internal Server Error –

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 Recharts

  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:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 200 OK – success

    - 400 Bad Request – no gpx file for this workout

    - 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

    - 500 Internal Server Error –

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:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 200 OK – success

    - 400 Bad Request – no gpx file for this workout

    - 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

    - 500 Internal Server Error –

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:

    - 200 OK – success

    - 401 Unauthorized –

      - provide a valid auth token

      - signature expired, please log in again

      - invalid token, please log in again

    - 404 Not Found – map does not exist

    - 500 Internal Server Error –

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 OK – success

    - 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",
                "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 and notes (example: `{"sport_id": 1, "notes": ""}`)

  Request Headers:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 201 Created – workout created

    - 400 Bad Request –

      - invalid payload

      - no file part

      - no selected file

      - file extension not allowed

    - 401 Unauthorized –

      - provide a valid auth token

      - signature expired, please log in again

      - invalid token, please log in again

    - 413 Request Entity Too Large – error during picture update: file size exceeds 1.0MB

    - 500 Internal Server Error –

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",
                "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:

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

    - distance (float) – workout distance in km

    - duration (integer) – workout duration in seconds

    - notes (string) – notes (not mandatory)

    - sport_id (integer) – workout sport id

    - title (string) – workout title

  Request Headers:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 201 Created – workout created

    - 400 Bad Request – invalid payload

    - 401 Unauthorized –

      - provide a valid auth token

      - signature expired, please log in again

      - invalid token, please log in again

    - 500 Internal Server Error –

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",
                "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:

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

    - 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

  Request Headers:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 200 OK – workout updated

    - 400 Bad Request – invalid payload

    - 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

    - 500 Internal Server Error –

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:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 204 No Content – workout deleted

    - 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

    - 500 Internal Server Error – error, please try again or contact the administrator