# Authentication

POST /api/auth/register

  Register a user and send confirmation email.

  The newly created account is inactive. The user must confirm his email to activate it.

  Example request:

      POST /api/auth/register HTTP/1.1
      Content-Type: application/json

  Example responses:

  - success

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

      {
        "status": "success"
      }

  - error on registration

      HTTP/1.1 400 BAD REQUEST
      Content-Type: application/json

      {
        "message": "Errors: email: valid email must be provided\n",
        "status": "error"
      }

  Request JSON Object:

    - username (string) – username (3 to 30 characters required)

    - email (string) – user email

    - password (string) – password (8 characters required)

    - lang (string) – user language preferences (if not provided or invalid, fallback to ‘en’ (english))

  Status Codes:

    - 200 OK – success

    - 400 Bad Request –

      - invalid payload

      - sorry, that username is already taken

      - Errors:

          - username: 3 to 30 characters required

          - username: only alphanumeric characters and the underscore character “_” allowed

          - email: valid email must be provided

          - password: 8 characters required

    - 403 Forbidden – error, registration is disabled

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

POST /api/auth/account/confirm

  Activate user account after registration.

  Example request:

      POST /api/auth/account/confirm HTTP/1.1
      Content-Type: application/json

  Example response:

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

      {
        "auth_token": "JSON Web Token",
        "message": "account confirmation successful",
        "status": "success"
      }

  Request JSON Object:

    - token (string) – confirmation token

  Status Codes:

    - 200 OK – account confirmation successful

    - 400 Bad Request – invalid payload

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

POST /api/auth/account/resend-confirmation

  Resend email with instructions to confirm account.

  If email sending is disabled, this endpoint is not available.

  Example request:

      POST /api/auth/account/resend-confirmation HTTP/1.1
      Content-Type: application/json

  Example response:

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

      {
        "message": "confirmation email resent",
        "status": "success"
      }

  Request JSON Object:

    - email (string) – user email

  Status Codes:

    - 200 OK – confirmation email resent

    - 400 Bad Request – invalid payload

    - 404 Not Found – the requested URL was not found on the server

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

POST /api/auth/login

  User login.

  Only user with an active account can log in.

  Example request:

      POST /api/auth/login HTTP/1.1
      Content-Type: application/json

  Example responses:

  - successful login

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

      {
        "auth_token": "JSON Web Token",
        "message": "successfully logged in",
        "status": "success"
      }

  - error on login

      HTTP/1.1 401 UNAUTHORIZED
      Content-Type: application/json

      {
        "message": "invalid credentials",
        "status": "error"
      }

  Request JSON Object:

    - email (string) – user email

    - password (string) – password

  Status Codes:

    - 200 OK – successfully logged in

    - 400 Bad Request – invalid payload

    - 401 Unauthorized – invalid credentials

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

GET /api/auth/profile

  Get authenticated user info (profile, account, preferences).

  Scope: `profile:read`

  Example request:

      GET /api/auth/profile HTTP/1.1
      Content-Type: application/json

  Example response:

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

      {
        "data": {
          "admin": false,
          "bio": null,
          "birth_date": null,
          "created_at": "Sun, 14 Jul 2019 14:09:58 GMT",
          "display_ascent": true,
          "email": "sam@example.com",
          "first_name": null,
          "imperial_units": false,
          "is_active": true,
          "language": "en",
          "last_name": null,
          "location": null,
          "nb_sports": 3,
          "nb_workouts": 6,
          "picture": false,
          "records": [
            {
              "id": 9,
              "record_type": "AS",
              "sport_id": 1,
              "user": "sam",
              "value": 18,
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            },
            {
              "id": 10,
              "record_type": "FD",
              "sport_id": 1,
              "user": "sam",
              "value": 18,
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            },
            {
              "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": 11,
              "record_type": "LD",
              "sport_id": 1,
              "user": "sam",
              "value": "1:01:00",
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            },
            {
              "id": 12,
              "record_type": "MS",
              "sport_id": 1,
              "user": "sam",
              "value": 18,
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            }
          ],
          "sports_list": [
              1,
              4,
              6
          ],
          "timezone": "Europe/Paris",
          "total_distance": 67.895,
          "total_duration": "6:50:27",
          "username": "sam",
          "weekm": false
        },
        "status": "success"
      }

  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

POST /api/auth/profile/edit

  Edit authenticated user profile.

  Scope: `profile:write`

  Example request:

      POST /api/auth/profile/edit HTTP/1.1
      Content-Type: application/json

  Example response:

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

      {
        "data": {
          "admin": false,
          "bio": null,
          "birth_date": null,
          "created_at": "Sun, 14 Jul 2019 14:09:58 GMT",
          "display_ascent": true,
          "email": "sam@example.com",
          "first_name": null,
          "imperial_units": false,
          "is_active": true,
          "language": "en",
          "last_name": null,
          "location": null,
          "nb_sports": 3,
          "nb_workouts": 6,
          "picture": false,
          "records": [
            {
              "id": 9,
              "record_type": "AS",
              "sport_id": 1,
              "user": "sam",
              "value": 18,
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            },
            {
              "id": 10,
              "record_type": "FD",
              "sport_id": 1,
              "user": "sam",
              "value": 18,
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            },
            {
              "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": 11,
              "record_type": "LD",
              "sport_id": 1,
              "user": "sam",
              "value": "1:01:00",
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            },
            {
              "id": 12,
              "record_type": "MS",
              "sport_id": 1,
              "user": "sam",
              "value": 18,
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            }
          ],
          "sports_list": [
              1,
              4,
              6
          ],
          "timezone": "Europe/Paris",
          "total_distance": 67.895,
          "total_duration": "6:50:27",
          "username": "sam"
          "weekm": true,
        },
        "message": "user profile updated",
        "status": "success"
      }

  Request JSON Object:

    - first_name (string) – user first name

    - last_name (string) – user last name

    - location (string) – user location

    - bio (string) – user biography

    - birth_date (string) – user birth date (format: `%Y-%m-%d`)

  Request Headers:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 200 OK – user profile 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

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

POST /api/auth/profile/edit/preferences

  Edit authenticated user preferences.

  Scope: `profile:write`

  Example request:

      POST /api/auth/profile/edit/preferences HTTP/1.1
      Content-Type: application/json

  Example response:

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

      {
        "data": {
          "admin": false,
          "bio": null,
          "birth_date": null,
          "created_at": "Sun, 14 Jul 2019 14:09:58 GMT",
          "display_ascent": true,
          "email": "sam@example.com",
          "first_name": null,
          "imperial_units": false,
          "is_active": true,
          "language": "en",
          "last_name": null,
          "location": null,
          "nb_sports": 3,
          "nb_workouts": 6,
          "picture": false,
          "records": [
            {
              "id": 9,
              "record_type": "AS",
              "sport_id": 1,
              "user": "sam",
              "value": 18,
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            },
            {
              "id": 10,
              "record_type": "FD",
              "sport_id": 1,
              "user": "sam",
              "value": 18,
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            },
            {
              "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": 11,
              "record_type": "LD",
              "sport_id": 1,
              "user": "sam",
              "value": "1:01:00",
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            },
            {
              "id": 12,
              "record_type": "MS",
              "sport_id": 1,
              "user": "sam",
              "value": 18,
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            }
          ],
          "sports_list": [
              1,
              4,
              6
          ],
          "timezone": "Europe/Paris",
          "total_distance": 67.895,
          "total_duration": "6:50:27",
          "username": "sam"
          "weekm": true,
        },
        "message": "user preferences updated",
        "status": "success"
      }

  Request JSON Object:

    - display_ascent (boolean) – display highest ascent records and total

    - imperial_units (boolean) – display distance in imperial units

    - language (string) – language preferences

    - timezone (string) – user time zone

    - weekm (boolean) – does week start on Monday?

  Request Headers:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 200 OK – user preferences updated

    - 400 Bad Request –

      - invalid payload

      - password: password and password confirmation don’t match

    - 401 Unauthorized –

      - provide a valid auth token

      - signature expired, please log in again

      - invalid token, please log in again

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

POST /api/auth/profile/edit/sports

  Edit authenticated user sport preferences.

  Scope: `profile:write`

  Example request:

      POST /api/auth/profile/edit/sports HTTP/1.1
      Content-Type: application/json

  Example response:

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

      {
        "data": {
          "color": "#000000",
          "is_active": true,
          "sport_id": 1,
          "stopped_speed_threshold": 1,
          "user_id": 1
        },
        "message": "user sport preferences updated",
        "status": "success"
      }

  Request JSON Object:

    - color (string) – valid hexadecimal color

    - is_active (boolean) – is sport available when adding a workout

    - stopped_speed_threshold (float) – stopped speed threshold used by gpxpy

  Request Headers:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 200 OK – user preferences updated

    - 400 Bad Request –

      - invalid payload

      - invalid hexadecimal color

    - 401 Unauthorized –

      - provide a valid auth token

      - signature expired, please log in again

      - invalid token, please log in again

    - 404 Not Found –

      - sport does not exist

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

DELETE /api/auth/profile/reset/sports/(sport_id)

  Reset authenticated user preferences for a given sport.

  Scope: `profile:write`

  Example request:

      DELETE /api/auth/profile/reset/sports/1 HTTP/1.1
      Content-Type: application/json

  Example response:

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

  Parameters:

    - sport_id (string) – sport id

  Request Headers:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 204 No Content – user preferences deleted

    - 401 Unauthorized –

      - provide a valid auth token

      - signature expired, please log in again

      - invalid token, please log in again

    - 404 Not Found –

      - sport does not exist

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

POST /api/auth/picture

  Update authenticated user picture.

  Scope: `profile:write`

  Example request:

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

  Example response:

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

      {
        "message": "user picture updated",
        "status": "success"
      }

  Form Parameters:

    - file – image file (allowed extensions: .jpg, .png, .gif)

  Request Headers:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 200 OK – user picture updated

    - 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 – error during picture update

DELETE /api/auth/picture

  Delete authenticated user picture.

  Scope: `profile:write`

  Example request:

      DELETE /api/auth/picture HTTP/1.1
      Content-Type: application/json

  Example response:

      HTTP/1.1 204 NO CONTENT
      Content-Type: application/json

  Request Headers:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 204 No Content – picture deleted

    - 401 Unauthorized –

      - provide a valid auth token

      - signature expired, please log in again

      - invalid token, please log in again

    - 500 Internal Server Error – error during picture deletion

POST /api/auth/password/reset-request

  Handle password reset request.

  If email sending is disabled, this endpoint is not available

  Example request:

      POST /api/auth/password/reset-request HTTP/1.1
      Content-Type: application/json

  Example response:

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

      {
        "message": "password reset request processed",
        "status": "success"
      }

  Request JSON Object:

    - email (string) – user email

  Status Codes:

    - 200 OK – password reset request processed

    - 400 Bad Request – invalid payload

    - 404 Not Found – the requested URL was not found on the server

PATCH /api/auth/profile/edit/account

  Update authenticated user email and password.

  It sends emails if sending is enabled:

  - Password change

  - Email change:

    - one to the current address to inform user

    - another one to the new address to confirm it.

  Scope: `profile:write`

  Example request:

      PATCH /api/auth/profile/edit/account HTTP/1.1
      Content-Type: application/json

  Example response:

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

      {
        "data": {
          "admin": false,
          "bio": null,
          "birth_date": null,
          "created_at": "Sun, 14 Jul 2019 14:09:58 GMT",
          "display_ascent": true,
          "email": "sam@example.com",
          "first_name": null,
          "imperial_units": false,
          "is_active": true,
          "language": "en",
          "last_name": null,
          "location": null,
          "nb_sports": 3,
          "nb_workouts": 6,
          "picture": false,
          "records": [
            {
              "id": 9,
              "record_type": "AS",
              "sport_id": 1,
              "user": "sam",
              "value": 18,
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            },
            {
              "id": 10,
              "record_type": "FD",
              "sport_id": 1,
              "user": "sam",
              "value": 18,
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            },
            {
              "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": 11,
              "record_type": "LD",
              "sport_id": 1,
              "user": "sam",
              "value": "1:01:00",
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            },
            {
              "id": 12,
              "record_type": "MS",
              "sport_id": 1,
              "user": "sam",
              "value": 18,
              "workout_date": "Sun, 07 Jul 2019 08:00:00 GMT",
              "workout_id": "hvYBqYBRa7wwXpaStWR4V2"
            }
          ],
          "sports_list": [
              1,
              4,
              6
          ],
          "timezone": "Europe/Paris",
          "total_distance": 67.895,
          "total_duration": "6:50:27",
          "username": "sam"
          "weekm": true,
        },
        "message": "user account updated",
        "status": "success"
      }

  Request JSON Object:

    - email (string) – user email

    - password (string) – user current password

    - new_password (string) – user new password

  Request Headers:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 200 OK – user account updated

    - 400 Bad Request –

      - invalid payload

      - email is missing

      - current password is missing

      - email: valid email must be provided

      - password: 8 characters required

    - 401 Unauthorized –

      - provide a valid auth token

      - signature expired, please log in again

      - invalid token, please log in again

      - invalid credentials

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

POST /api/auth/password/update

  Update user password after password reset request.

  It sends emails if sending is enabled.

  Example request:

      POST /api/auth/password/update HTTP/1.1
      Content-Type: application/json

  Example response:

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

      {
        "message": "password updated",
        "status": "success"
      }

  Request JSON Object:

    - password (string) – password (8 characters required)

    - token (string) – password reset token

  Status Codes:

    - 200 OK – password updated

    - 400 Bad Request – invalid payload

    - 401 Unauthorized – invalid token, please request a new token

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

POST /api/auth/email/update

  Update user email after confirmation.

  Example request:

      POST /api/auth/email/update HTTP/1.1
      Content-Type: application/json

  Example response:

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

      {
        "message": "email updated",
        "status": "success"
      }

  Request JSON Object:

    - token (string) – password reset token

  Status Codes:

    - 200 OK – email updated

    - 400 Bad Request – invalid payload

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

POST /api/auth/logout

  User logout. If a valid token is provided, it will be blacklisted.

  Example request:

      POST /api/auth/logout HTTP/1.1
      Content-Type: application/json

  Example responses:

  - successful logout

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

      {
        "message": "successfully logged out",
        "status": "success"
      }

  - error on logout

      HTTP/1.1 401 UNAUTHORIZED
      Content-Type: application/json

      {
        "message": "provide a valid auth token",
        "status": "error"
      }

  Request Headers:

    - Authorization – OAuth 2.0 Bearer Token

  Status Codes:

    - 200 OK – successfully logged out

    - 401 Unauthorized –

      - provide a valid auth token

      - The access token provided is expired, revoked, malformed, or invalid for other reasons.

    - 500 Internal Server Error –

      - error on token blacklist