Introduction

The WakaTime API follows common REST conventions. This means you should use GET requests to retrieve data and POST, PUT, or PATCH requests to modify data. All API requests must be done over HTTPS.

Every response will be a JSON object, which is a key-value hash. Data for a resource will be returned in the key named data. Errors will be returned in the key named errors or error.

HTTP response codes indicate the status of your request:

  • 200 - Ok: The request has succeeded.
  • 201 - Created: The request has been fulfilled and resulted in a new resource being created.
  • 202 - Accepted: The request has been accepted for processing, but the processing has not been completed. The stats resource may return this code.
  • 400 - Bad Request: The request is invalid. Check error message and try again.
  • 401 - Unauthorized: The request requires authentication, or your authentication was invalid.
  • 403 - Forbidden: You are authenticated, but do not have permission to access the resource.
  • 404 - Not Found: The resource does not exist.
  • 429 - Too Many Requests: You are being rate limited, try making fewer than 10 requests per second on average over any 5 minute period.
  • 500 - Server Error: Service unavailable, try again later.

All API resources have the url prefix https://wakatime.com/api/v1/.

When using the WakaTime trademark or logo in your application, please follow our usage guidelines.

Security

Do NOT use the API with your secret key on a public website. Instead, create an embeddable chart that's safe to share publicly. Choose the JSON format to securely access your coding activity with JavaScript:

Embeddable SVG Charts and JSON

Authentication

OAuth 2.0 Endpoints

Create an app to get an OAuth 2.0 client token.

The OAuth 2.0 provider endpoints are:

  • https://wakatime.com/oauth/authorize - Redirect your users here to request permission to access their account. Required url arguments are client_id, response_type of code or token, redirect_uri, scope. Optional parameters are state and force_approve.
  • https://wakatime.com/oauth/token - Make a server-side POST request here to get the secret access token. Required x-www-form-urlencoded data is client_id, client_secret, redirect_uri must be the same url used in authorize step, grant_type of authorization_code, and the code received from the authorize step.
  • https://wakatime.com/oauth/revoke - Make a server-side POST request here to invalidate a secret access token. Required x-www-form-urlencoded data is client_id, client_secret, and the token (access or refresh) to be invalidated.

For information about using these endpoints, see RFC6749 OAuth 2.0.

Using Access Token

After getting the bearer (access) token from https://wakatime.com/oauth/token, you can now make authenticated api calls using the Authorization request header (RFC 6750).

For example, if your user's access token is sec_12345, you would add this header to your request:
Authorization: Bearer sec_12345.

Alternatively, you can authenticate with url args named access_token, or just token and app_secret, client_secret, or just secret.

Using the Refresh Token

You should always get a refresh_token from the /oauth/token response. The refresh_token can be used when your access_token has expired, to re-authorize without having to prompt the user.

To use the refresh_token, make a POST request to https://wakatime.com/oauth/token to get a new secret access token. Required x-www-form-urlencoded data is client_id, client_secret, redirect_uri must be the same url used in authorize step, grant_type of refresh_token, and the refresh_token received from a previous token response.

Revoking a Token

Your app should revoke tokens when users disconnect their WakaTime integration, delete their account on your app, or you no longer need access to a user’s account. To revoke an access token, and it’s corresponding refresh token, send a POST request to /oauth/revoke containing either JSON or form-urlencoded body containing your app’s client_id, client_secret, and the token (access or refresh token) that you would like to revoke. The response status will be 200 success if the token is successfully disabled. If the token is already revoked or expired, this endpoint will still respond with a 200 success response.

For example:

POST /oauth/revoke HTTP/1.1 Host: wakatime.com Content-Type: application/x-www-form-urlencoded client_id=XXX client_secret=sec_XXX token=sec_12345

Available Scopes

Scopes are sent to the authorize url as a comma separated list.

  • email - access user’s email and identity information.
  • read_logged_time - access user’s coding activity and other stats.
  • write_logged_time - modify user’s coding activity.
  • read_stats - access user’s languages, editors, and operating systems used.
  • read_orgs - access user’s organizations, and coding activity for dashboard members.
  • read_private_leaderboards - access user’s private leaderboards.
  • write_private_leaderboards - modify user’s private leaderboards, including adding/removing members when current user had Admin or Owner role.

Example

OAuth 2.0 authentication flow using rauth (Python):

#!/usr/bin/env python

import hashlib
import os
import sys
from rauth import OAuth2Service

if sys.version_info[0] == 3:
    raw_input = input

client_id = raw_input('Enter your App Id: ')
secret = raw_input('Enter your App Secret: ')

service = OAuth2Service(
    client_id=client_id,  # your App ID from https://wakatime.com/apps
    client_secret=secret,  # your App Secret from https://wakatime.com/apps
    name='wakatime',
    authorize_url='https://wakatime.com/oauth/authorize',
    access_token_url='https://wakatime.com/oauth/token',
    base_url='https://wakatime.com/api/v1/')

redirect_uri = 'https://wakatime.com/oauth/test'
state = hashlib.sha1(os.urandom(40)).hexdigest()
params = {'scope': 'email,read_stats',
          'response_type': 'code',
          'state': state,
          'redirect_uri': redirect_uri}

url = service.get_authorize_url(**params)

print('**** Visit this url in your browser ****'.format(url=url))
print('*' * 80)
print(url)
print('*' * 80)
print('**** After clicking Authorize, paste code here and press Enter ****')
code = raw_input('Enter code from url: ')

# Make sure returned state has not changed for security reasons, and exchange
# code for an Access Token.
headers = {'Accept': 'application/x-www-form-urlencoded'}
print('Getting an access token...')
session = service.get_auth_session(headers=headers,
                                   data={'code': code,
                                         'grant_type': 'authorization_code',
                                         'redirect_uri': redirect_uri})

print('Getting current user from API...')
user = session.get('users/current').json()
print('Authenticated via OAuth as {0}'.format(user['data']['email']))
print("Getting user's coding stats from API...")
stats = session.get('users/current/stats')
print(stats.text)

Using refresh_token to get a new access_token when the previous one has expired, using rauth (Python):

from urllib.parse import parse_qsl

refresh_token = dict(parse_qsl(session.access_token_response.text))['refresh_token']

data = {
    'refresh_token': refresh_token,
    'grant_type': 'refresh_token',
}
session = service.get_auth_session(data=data)

400 Error (Invalid redirect_uri: Not valid for this client.)

If you see this error when running the example, add https://wakatime.com/oauth/test as an authorized redirect url in your App's settings.

Using API Key

Most apps should use OAuth, but you can also authenticate to the WakaTime API using your secret API Key.

Using HTTP Basic Auth pass your API Key base64 encoded in the Authorization header. Don't forget to prepend Basic to your api key after base64 encoding it.

For example, when using HTTP Basic Auth with an api key of 12345 you should add this header to your request:
Authorization: Basic MTIzNDU=

That’s because when you decode the base64 string "MTIzNDU=" you get "12345".

Alternatively, you can pass your api key as a query parameter in your request like ?api_key=XXXX.

Do NOT use your API Key on a public website. Instead, use embeddable charts and JSON.

Writing your own plugin

WakaTime plugins are extensions that run inside your text editor or IDE sending usage stats, called heartbeats, to your WakaTime Dashboard. All official WakaTime plugins are open source on GitHub.

When building your own editor plugin, use our Creating a WakaTime plugin guide.

Embedding Charts & JSON

Want to share your WakaTime stats? Use the embeddable charts and JSON to safely embed your coding activity on a public website without leaking your secret api key. Select the JSON format for access to your coding stats in JavaScript. We don’t support Cross-Origin Resource Sharing (CORS) because the only way to access your coding stats safely in public JavaScript is with embeddable JSON. Embeddable JSON does support JSONP. Embeddable charts and JSON use a one-time unique url and can be retracted to prevent future access to your coding stats.

Never use the WakaTime API from a public website, except for embeddables. Using your secret api key in client-side JavaScript gives everyone on the internet full access to your WakaTime account.

All Time Since Today

GET /api/v1/users/:user/all_time_since_today

GET /api/v1/users/current/all_time_since_today

Description

The total time logged since account created, available even for Free accounts.

URL Parameters

project - String - optional - Shows the total time for a project, since project created.

Scope Required

read_stats

Example Response

Response Code: 200

{
  "data": {
    "seconds": <float: total number of seconds logged since account created>,
    "text": <string: total time logged since account created as human readable string>,
    "is_up_to_date": <boolean: true if the stats are up to date; when false, a 202 response code is returned and stats will be refreshed soon>,
  }
}

Commit

GET /api/v1/users/:user/projects/:project/commits/:hash

GET /api/v1/users/current/projects/:project/commits/:hash

Description

A single commit from a WakaTime project showing the time spent coding on the commit.

URL Parameters

branch - String - optional - Filter the commit to a branch; defaults to the repo’s default branch name.

Scope Required

read_logged_time

Example Response

Response Code: 200

{
  "commit": {
    "author_avatar_url": <string: url of author's avatar image>
    "author_date": <string: time when commit was authored in ISO 8601 format>,
    "author_email": <string: email address of author>,
    "author_html_url": <string: link to author's profile on GitHub, Bitbucket, GitLab, etc>,
    "author_name": <string: name of author>,
    "author_url": <string: api url for author's profile>,
    "author_username": <string: author's username>,
    "branch": <string: branch name, for ex: master>,
    "committer_avatar_url": <string: url of committer's avatar image>,
    "committer_date": <string: commit time in ISO 8601 format>,
    "committer_email": <string: email address of committer>,
    "committer_html_url": <string: link to committer's profile on GitHub, Bitbucket, GitLab, etc>,
    "committer_name": <string: name of committer>,
    "committer_url": <string: api url for committer's profile>,
    "committer_username": <string: committer's username>,
    "created_at": <string: time commit was synced in ISO 8601 format>,
    "hash": <string: revision control hash of this commit>,
    "html_url": <string: link to an html page with details about current commit>,
    "human_readable_total": <string: time coded in editor for this commit>,
    "human_readable_total_with_seconds": <string: time coded in editor for this commit>,
    "id": <string: unique id of commit>,
    "message": <string: author's description of this commit>,
    "ref": <string: refs/heads/master>,
    "total_seconds": <float: time coded in editor for this commit>,
    "truncated_hash": <string: truncated revision control hash of this commit>,
    "url": <string: api url with details about current commit>,
  },
  "branch": <string: branch name containting the commit>,
  "project": {
    "id": <string: unique id of project>,
    "name": <string: project name>,
    "privacy": <string: project privacy setting>,
    "repository": {
      "default_branch": <string: default branch if given for this repo>,
      "description": <string: remote repository description>,
      "fork_count": <integer: number of repo forks if available>
      "full_name": <string: username and repo name, ex: wakatime/wakadump>,
      "homepage": <string: homepage of repository>,
      "html_url": <string: html url for repository>,
      "id": <string: unique id of repository>,
      "is_fork": <boolean: whether this repo is a fork or original>,
      "is_private": <boolean: whether this repo is private or public>,
      "last_synced_at": <string: last time this repo was synced with remote provider iSO 8601 format>,
      "name": <string: repository name>,
      "provider": <string: remote provider of repository, ex: github>,
      "star_count": <integer: number of repo stars if available>
      "url": <string: api url of remote repository>,
      "watch_count": <integer: number of watchers of repo if available>,
    }
  },
  "status": <string: project's sync status>,
}

Commits

GET /api/v1/users/:user/projects/:project/commits

GET /api/v1/users/current/projects/:project/commits

Description

List of commits for a WakaTime project showing the time spent coding in each commit.

URL Parameters

author - String - optional - Filter commits to only those authored by the given username.

branch - String - optional - Filter commits to a branch; defaults to the repo’s default branch name.

page - Integer - optional - Page number of commits.

Scope Required

read_logged_time

Example Response

Response Code: 200

{
  "commits": [
    {
      "author_avatar_url": <string: url of author's avatar image>
      "author_date": <string: time when commit was authored in ISO 8601 format>,
      "author_email": <string: email address of author>,
      "author_html_url": <string: link to author's profile on GitHub, Bitbucket, GitLab, etc>,
      "author_name": <string: name of author>,
      "author_url": <string: api url for author's profile>,
      "author_username": <string: author's username>,
      "branch": <string: branch name, for ex: master>,
      "committer_avatar_url": <string: url of committer's avatar image>,
      "committer_date": <string: commit time in ISO 8601 format>,
      "committer_email": <string: email address of committer>,
      "committer_html_url": <string: link to committer's profile on GitHub, Bitbucket, GitLab, etc>,
      "committer_name": <string: name of committer>,
      "committer_url": <string: api url for committer's profile>,
      "committer_username": <string: committer's username>,
      "created_at": <string: time commit was synced in ISO 8601 format>,
      "hash": <string: revision control hash of this commit>,
      "html_url": <string: link to an html page with details about current commit>,
      "human_readable_total": <string: time coded in editor for this commit>,
      "human_readable_total_with_seconds": <string: time coded in editor for this commit>,
      "id": <string: unique id of commit>,
      "message": <string: author's description of this commit>,
      "ref": <string: refs/heads/master>,
      "total_seconds": <float: time coded in editor for this commit>,
      "truncated_hash": <string: truncated revision control hash of this commit>,
      "url": <string: api url with details about current commit>,
    }, …
  ],
  "author": <string: current author or null if showing commits from all authors>,
  "next_page": <integer: next page number or null if last page>
  "next_page_url": <string: url for next page or null if last page>
  "page": <integer: current page number>
  "prev_page": <integer: previous page number or null if first page>
  "prev_page_url": <string: url for previous page or null if first page>
  "branch": <string: branch name containting the commits>,
  "project": {
    "id": <string: unique id of project>,
    "name": <string: project name>,
    "privacy": <string: project privacy setting>,
    "repository": {
      "default_branch": <string: default branch if given for this repo>,
      "description": <string: remote repository description>,
      "fork_count": <integer: number of repo forks if available>
      "full_name": <string: username and repo name, ex: wakatime/wakadump>,
      "homepage": <string: homepage of repository>,
      "html_url": <string: html url for repository>,
      "id": <string: unique id of repository>,
      "is_fork": <boolean: whether this repo is a fork or original>,
      "is_private": <boolean: whether this repo is private or public>,
      "last_synced_at": <string: last time this repo was synced with remote provider iSO 8601 format>,
      "name": <string: repository name>,
      "provider": <string: remote provider of repository, ex: github>,
      "star_count": <integer: number of repo stars if available>
      "url": <string: api url of remote repository>,
      "watch_count": <integer: number of watchers of repo if available>,
    }
  },
  "status": <string: project's sync status>,
  "total": <integer: number of commits available>,
  "total_pages": <integer: number of pages available>,
}

Data Dumps

GET /api/v1/users/:user/data_dumps

GET /api/v1/users/current/data_dumps

Description

List data exports for the user. A data export can also be created at https://wakatime.com/settings, and contains all the user’s coding stats as daily Summaries in JSON format since the user’s account was created.

Scope Required

read_logged_time

Example Response

Response Code: 200

{
  "data": [
    {
      "id": <string: unique id of this data export>,
      "status": <string: one of 'Pending…', 'Processing coding activity…', 'Uploading…', or 'Completed'>,
      "percent_complete": <float: percent of coding stats that have been exported>,
      "download_url": <string: when completed, the url to download this data export>,
      "expires": <string: datetime when this data export can no longer be downloaded>,
      "created_at": <string: datetime when this data export was requested>,
    }, …
  ],
}


POST /api/v1/users/:user/data_dumps

POST /api/v1/users/current/data_dumps

Description

Start generating a data export in the background. When finished, the percent complete will be 100 and the status 'Completed', with a 'download_url' available for downloading. An email will also be sent to the user with the download url when exporting completed.

Scope Required

read_logged_time

JSON POST Data

{
  "email_when_finished": <boolean: Optional flag to disable the email notification when exporting completed; defaults to true>,
}

Example Response

Response Code: 201

{
  "data": {
    "id": <string: unique id of this data export>,
    "status": <string: one of 'Pending…', 'Processing coding activity…', 'Uploading…', or 'Completed'>,
    "percent_complete": <float: percent of coding stats that have been exported>,
    "download_url": <string: when completed, the url to download this data export>,
    "expires": <string: datetime when this data export can no longer be downloaded>,
    "created_at": <string: datetime when this data export was requested>,
  },
}

Durations

GET /api/v1/users/:user/durations

GET /api/v1/users/current/durations

Description

A user's coding activity for the given day as an array of durations. Durations are read-only representations of Heartbeats, created by joining multiple Heartbeats together when they’re within 15 minutes of each other. The 15 minutes default can be changed with your account’s Timeout preference.

URL Parameters

date - Date - required - Requested day; Durations will be returned from 12am until 11:59pm in user's timezone for this day.

project - String - optional - Only show durations for this project.

branches - String - optional - Only show durations for these branches; comma separated list of branch names.

timeout - Integer - optional - The timeout preference used when joining heartbeats into durations. Defaults the the user's timeout value. See the FAQ for more info.

writes_only - Boolean - optional - The writes_only preference. Defaults to the user's writes_only setting.

timezone - String - optional - The timezone for given date. Defaults to the user's timezone.

slice_by - String - optional - Optional primary key to use when slicing durations. Defaults to “entity”. Can be “entity”, “language”, “dependencies”, “os”, “editor”, “category”, or “machine”.

Scope Required

read_logged_time

Example Response

Response Code: 200

{
  "data": [
    {
      "project": <string: project name>,
      "time": <float: start of this duration as UNIX epoch; numbers after decimal point are fractions of a second>,
      "duration": <float: length of time of this duration in seconds>
    }, …
  ],
  "branches": <list of strings: branches included in this response>,
  "start": <string: start of time range as ISO 8601 UTC datetime>,
  "end": <string: end of time range as ISO 8601 UTC datetime>,
  "timezone": <string: timezone used for this request in Olson Country/Region format>
}

Editors

GET /api/v1/editors

Description

List of WakaTime IDE plugins, latest plugin versions, and their color used on WakaTime charts.

URL Parameters

unreleased - Boolean - optional - Include unreleased plugins.

Example Response

Response Code: 200

{
  "data": {
    "id": <string: unique id of this editor plugin>,
    "name": <string: display name of the editor>,
    "color": <string: hex color code used when displaying the editor on charts>,
    "website": <string: official website of the editor>,
    "repository": <string: github repository for the editor’s plugin>,
    "version": <string: most recent plugin version available for this editor>,
    "version_url": <string: remote file containing this editor’s most recent version>,
    "history_url": <string: changelog file>,
    "released": <boolean: whether this IDE has a WakaTime plugin available>,
  },
}

Try it out

External Durations

GET /api/v1/users/:user/external_durations

GET /api/v1/users/current/external_durations

Description

A user's external durations for the given day. External durations aren’t created by IDE plugins. They’re created from external apps, such as the Google Calendar integration. They should be reproducible from the external integration. External durations for an integration are deleted when the user disconnects the integration from their WakaTime account.

URL Parameters

date - Date - required - Requested day; Durations will be returned from 12am until 11:59pm in user's timezone for this day.

project - String - optional - Only show durations for this project.

branches - String - optional - Only show durations for these branches; comma separated list of branch names.

timezone - String - optional - The timezone for given date. Defaults to the user's timezone.

Scope Required

read_logged_time

Example Response

Response Code: 200

{
  "data": [
    {
      "id": <string: unique id of this external duration>,
      "external_id": <string: unique identifier for this duration on the external provider>,
      "entity": <string: entity duration is logging time against, such as an absolute file path or domain>,
      "type": <string: type of entity; can be file, app, or domain>,
      "provider": <string: external app which created this activity>,
      "category": <string: category for this activity; can be coding, building, indexing, debugging, browsing, running tests, writing tests, manual testing, writing docs, code reviewing, researching, learning, or designing>,
      "start_time": <float: UNIX epoch timestamp; numbers after decimal point are fractions of a second>,
      "end_time": <float: UNIX epoch timestamp; numbers after decimal point are fractions of a second>,
      "project": <string: project name (optional)>,
      "branch": <string: branch name (optional)>,
      "language": <string: language name (optional)>,
    }, …
  ],
  "start": <string: start of time range as ISO 8601 UTC datetime>,
  "end": <string: end of time range as ISO 8601 UTC datetime>,
  "timezone": <string: timezone used for this request in Olson Country/Region format>
}


POST /api/v1/users/:user/external_durations

POST /api/v1/users/current/external_durations

POST /api/v1/users/:user/external_durations.bulk

POST /api/v1/users/current/external_durations.bulk

Description

Creates a duration representing activity for a user with start and end time, when Heartbeat pings aren’t available. For ex: meetings. External durations are not created by IDE plugins, only OAuth apps can create external durations. External durations must be created within one year from Today, and must not start before the associated user’s account was created. Use external_id to prevent creating duplicate durations. Using the same external_id will update any existing duration with the provided attributes. The bulk endpoint accepts an array of external durations, limited to 1,000 per POST request. The bulk endpoint will return 201 response status code with an array of status_codes for each duration sent. That’s because most invalid durations can be ommitted without problems while still allowing your app’s valid durations.

Scope Required

write_logged_time

JSON POST Data

{
  "external_id": <string: unique identifier for this duration on the external provider>,
  "entity": <string: entity which this duration is logging time towards, such as an absolute file path or a domain>,
  "type": <string: type of entity; can be file, app, or domain>,
  "category": <string: category for this activity (optional); normally this is inferred automatically from type; can be coding, building, indexing, debugging, browsing, running tests, writing tests, manual testing, writing docs, code reviewing, researching, learning, or designing>,
  "start_time": <float: UNIX epoch timestamp when the activity started; numbers after decimal point are fractions of a second>,
  "end_time": <float: UNIX epoch timestamp when the activity ended; numbers after decimal point are fractions of a second>,
  "project": <string: project name (optional)>,
  "branch": <string: branch name (optional)>,
  "language": <string: language name (optional)>,
}

Example Response

Response Code: 201

{
  "data": {
    "id": <string: unique id of this external duration>,
    "external_id": <string: unique identifier for this duration on the external provider>,
    "entity": <string: entity duration is logging time against, such as an absolute file path or domain>,
    "type": <string: type of entity; can be file, app, or domain>,
    "provider": <string: external app which created this activity>,
    "category": <string: category for this activity; can be coding, building, indexing, debugging, browsing, running tests, writing tests, manual testing, writing docs, code reviewing, researching, learning, or designing>,
    "start_time": <float: UNIX epoch timestamp; numbers after decimal point are fractions of a second>,
    "end_time": <float: UNIX epoch timestamp; numbers after decimal point are fractions of a second>,
    "project": <string: project name (optional)>,
    "branch": <string: branch name (optional)>,
    "language": <string: language name (optional)>,
  },
}

Goals

GET /api/v1/users/:user/goals

GET /api/v1/users/current/goals

Description

List a user’s goals.

Scope Required

read_logged_time

Example Response

Response Code: 200

{
  "data": [
    {
      "average_status": <string: "fail" when there are more failure days or weeks than success, otherwise "success">,
      "chart_data": {
        "actual_seconds": <float: number of seconds coded during this delta period>,
        "actual_seconds_text": <string: human readable time coded during this delta period>,
        "goal_seconds": <integer: number of seconds required to meet goal for this delta period>,
        "goal_seconds_text": <string: human readable coding time required to meet goal for this delta period>,
        "range": {
          "date": <string: current time range as Date string in YEAR-MONTH-DAY format (only available when delta is "day")>,
          "end": <string: end of current time range as ISO 8601 UTC datetime>,
          "start": <string: start of current time range as ISO 8601 UTC datetime>,
          "text": <string: current range in human-readable format relative to the current day>,
          "timezone": <string: timezone used in Olson Country/Region format>
        },
        "range_status": <string: either "success", "fail", "pending", or "ignored">
        "range_status_reason": <string: an explanation for why this delta period passed or failed>
      },
      "cumulative_status": <string: status over all delta periods, either "success", "fail", or "ignored">,
      "delta": <string: goal step duration; either "day" or "week">,
      "id": <string: unique id of goal>,
      "ignore_days": <list of strings: goal status set to "ignored" instead of "failed" for these weekdsays, when delta is "day">,
      "improve_by_percent": <float: percent goal should increase each delta>,
      "is_enabled": <boolean: whether this goal is enabled or disabled>,
      "languages": <list of strings: languages for this goal>,
      "projects": <list of strings: projects for this goal>,
      "range_text": <string: complete range of this goal for all delta periods in human-readable format>,
      "seconds": <integer: goal amount>,
      "status": <string: most recent day or week range status; can be "success", "fail", "ignored", or "pending">,
      "subscribers": [
        {
          "email": <string: email address of this subscriber, if public>,
          "email_frequency": <string: how often this subscriber receives emails about this goal>,
          "full_name": <string: name of this subscriber, if public>,
          "user_id": <string: unique id of this subscriber>,
          "username": <string: username of this subscriber, if defined>
        }, …
      ],
      "title": <string: human readable title for this goal>,
      "type": <string: type of goal>
    }, …
  ],
  "total": <integer: number of goals>,
  "total_pages": <integer: number of pages>,
}

Heartbeats

GET /api/v1/users/:user/heartbeats

GET /api/v1/users/current/heartbeats

Description

A user's heartbeats sent from plugins for the given day as an array.

URL Parameters

date - Date - required - Requested day; Heartbeats will be returned from 12am until 11:59pm in user's timezone for this day.

Scope Required

read_logged_time

Example Response

Response Code: 200

{
  "data": [
    {
      "entity": <string: entity heartbeat is logging time against, such as an absolute file path or domain>,
      "type": <string: type of entity; can be file, app, or domain>,
      "category": <string: category for this activity; can be coding, building, indexing, debugging, browsing, running tests, writing tests, manual testing, writing docs, code reviewing, researching, learning, or designing>,
      "time": <float: UNIX epoch timestamp; numbers after decimal point are fractions of a second>,
      "project": <string: project name (optional)>,
      "branch": <string: branch name (optional)>,
      "language": <string: language name (optional)>,
      "dependencies": <string: optional comma separated list of dependencies detected from entity file (optional)>,
      "machine_name_id": <string: unique id of the machine which generated this coding activity>,
      "lines": <integer: total number of lines in the entity (when entity type is file)>,
      "lineno": <integer: current line row number of cursor (optional)>,
      "cursorpos": <integer: current cursor column position (optional)>,
      "is_write": <boolean: whether this heartbeat was triggered from writing to a file>,
    }, …
  ],
  "start": <string: start of time range as ISO 8601 UTC datetime>,
  "end": <string: end of time range as ISO 8601 UTC datetime>,
  "timezone": <string: timezone used for this request in Olson Country/Region format>
}


POST /api/v1/users/:user/heartbeats

POST /api/v1/users/current/heartbeats

POST /api/v1/users/:user/heartbeats.bulk

POST /api/v1/users/current/heartbeats.bulk

Description

Creates a heartbeat representing activity for a user. The bulk endpoint accepts an array of heartbeats, limited to 25 per POST request.

Scope Required

write_logged_time

JSON POST Data

{
  "entity": <string: entity heartbeat is logging time against, such as an absolute file path or domain>,
  "type": <string: type of entity; can be file, app, or domain>,
  "category": <string: category for this activity (optional); normally this is inferred automatically from type; can be coding, building, indexing, debugging, browsing, running tests, writing tests, manual testing, writing docs, code reviewing, researching, learning, or designing>,
  "time": <float: UNIX epoch timestamp; numbers after decimal point are fractions of a second>,
  "project": <string: project name (optional)>,
  "branch": <string: branch name (optional)>,
  "language": <string: language name (optional)>,
  "dependencies": <string: comma separated list of dependencies detected from entity file (optional)>,
  "lines": <integer: total number of lines in the entity (when entity type is file)>,
  "lineno": <integer: current line row number of cursor with the first line starting at 1 (optional)>,
  "cursorpos": <integer: current cursor column position starting from 1 (optional)>,
  "is_write": <boolean: whether this heartbeat was triggered from writing to a file (optional)>,
}

Example Response

Response Code: 201

{
  "data": {
    "id": <string: unique id of newly created heartbeat>,
    "entity": <string: entity heartbeat is logging time against, such as an absolute file path or domain>,
    "type": <string: type of entity; can be file, app, or domain>,
    "time": <float: UNIX epoch timestamp; numbers after decimal point are fractions of a second>,
  }
}

Leaders

GET /api/v1/leaders

Description

List of users ranked by coding activity in descending order. Same as the public leaderboards. The public leaderboard updates at least once every 12 hours, and usually more frequently.

URL Parameters

language - String - optional - Filter leaders by a specific language.

page - Integer - optional - Page number of leaderboard.

Example Response

Response Code: 200

{
  "current_user": {
    "rank": <integer: rank of the currently authorized user>,
    "running_total": {
      "total_seconds": <float: total coding activity for this user as seconds>,
      "human_readable_total": <string: total coding activity for this user as human readable string>,
      "daily_average": <float: daily average for this user as seconds>,
      "human_readable_daily_average": <string: daily average for this user as human readable string>,
      "languages": [
        {
          "name": <string: language name>,
          "total_seconds": <float: total seconds user has logged in this language>,
        }, …
      ],
    },
    "user": {
      "id": <string: unique id of user>,
      "email": <string: email address of user, if public>,
      "username": <string: users public username>,
      "full_name": <string: full name of user>,
      "display_name": <string: display name of this user taken from full_name or @username. Defaults to 'Anonymous User'>,
      "website": <string: website of user>,
      "human_readable_website": <string: website of user without url scheme>,
      "is_hirable": <boolean: represents the “hireable” badge on user profiles>,
      "location": <string: location of user>,
      "is_email_public": <boolean: whether this user's email should be shown publicly on leader boards>,
      "photo_public": <boolean: whether this user's photo should be shown publicly on leader boards>,
    },
  },
  "data": [
    {
      "rank": <integer: rank of this leader>,
      "running_total": {
        "total_seconds": <float: total coding activity for this user as seconds>,
        "human_readable_total": <string: total coding activity for this user as human readable string>,
        "daily_average": <float: daily average for this user as seconds>,
        "human_readable_daily_average": <string: daily average for this user as human readable string>,
        "languages": [
          {
            "name": <string: language name>,
            "total_seconds": <float: total seconds user has logged in this language>,
          }, …
        ],
      },
      "user": {
        "id": <string: unique id of user>,
        "email": <string: email address of user, if public>,
        "username": <string: users public username>,
        "full_name": <string: full name of user>,
        "display_name": <string: display name of this user taken from full_name or @username. Defaults to 'Anonymous User'>,
        "website": <string: website of user>,
        "human_readable_website": <string: website of user without url scheme>,
        "location": <string: location of user>,
        "is_email_public": <boolean: whether this user's email should be shown publicly on leader boards>,
        "photo_public": <boolean: whether this user's photo should be shown publicly on leader boards>,
      },
    }, …
  ],
  "page": <integer: current page number>
  "total_pages": <integer: number of pages available>,
  "range": {
    "start_date": <string: start of this range as ISO 8601 UTC datetime>,
    "start_text": <string: start of range in human-readable format relative to the current day>,
    "end_date": <string: end of range as ISO 8601 UTC datetime>,
    "end_text": <string: end of range in human-readable format relative to the current day>,
    "name": <string: time range of this leaderboard>,
    "text": <string: time range in human-readable format relative to the current day>,
  }
  "language": <string: language of this leaderboard>,
  "modified_at": <string: time when this leaderboard was last updated in ISO 8601 format>
  "timeout": <integer: timeout setting in minutes used by this leaderboard>,
  "writes_only": <boolean: writes_only setting used by this leaderboard>,
}

Try it out

Machine Names

GET /api/v1/users/:user/machine_names

GET /api/v1/users/current/machine_names

Description

List of machines for this user.

Scope Required

read_logged_time

Example Response

Response Code: 200

{
  "data": {
    "id": <string: unique id of this machine>,
    "name": <string: the machine’s name, normally the host name; when user’s preference is to show IPs in machine names, this will include the IP address of the machine.>,
    "value": <string: local host name of this machine>,
    "ip": <string: ip address of this machine>,
    "last_seen_at": <string: time when this machine was last seen in ISO 8601 format>,
    "created_at": <string: time when this machine was first seen in ISO 8601 format>,
  },
}

Meta

GET /api/v1/meta

Description

Information about WakaTime, such as a list of public ip addresses used by WakaTime servers.

Example Response

Response Code: 200

{
  "data": {
    "ip_descriptions": <object: explanation of each ip category (api, website, worker)>,
    "ips": {
      "api": <list of strings: ip addresses used by WakaTime api servers>,
      "website": <list of strings: ip addresses used by WakaTime website servers>,
      "worker": <list of strings: ip addresses used by WakaTime background worker servers>
    },
    "last_modified_at": <string: last time an IP was either added, removed, or modified in ISO 8601 format; use similar to etag, to sync your firewall configs only when IPs have changed>
  },
}

Try it out

Org Dashboard Member Durations

GET /api/v1/users/:user/orgs/:org/dashboards/:dashboard/members/:member/durations

GET /api/v1/users/current/orgs/:orgs/dashboards/:dashboard/members/:member/durations

Description

A dashboard member's coding activity for the given day as an array of durations.

URL Parameters

date - Date - required - Date in YYYY-MM-DD format.

project - String - optional - Only show durations for this project.

branches - String - optional - Only show durations for these branches; comma separated list of branch names.

Scope Required

read_orgs

Example Response

Response Code: 200

{
  "data": [
    {
      "project": <string: project name>,
      "time": <float: start of this duration as ISO 8601 UTC datetime; numbers after decimal point are fractions of a second>,
      "duration": <float: length of time of this duration in seconds>
    }, …
  ],
  "start": <string: start of time range as ISO 8601 UTC datetime>,
  "end": <string: end of time range as ISO 8601 UTC datetime>,
  "timezone": <string: timezone used for this request in Olson Country/Region format>
}

Org Dashboard Member Summaries

GET /api/v1/users/:user/orgs/:org/dashboards/:dashboard/members/:member/summaries

GET /api/v1/users/current/orgs/:org/dashboards/:dashboard/members/:member/summaries

Description

An organization dashboard member’s coding activity for the given time range as an array of summaries segmented by day.

URL Parameters

start - Date - required - Start date of the time range.

end - Date - required - End date of the time range.

project - String - optional - Only show time logged to this project.

branches - String - optional - Only show coding activity for these branches; comma separated list of branch names.

range - String - optional - Alternative way to supply start and end dates. Can be one of “Today”, “Yesterday”, “Last 7 Days”, “Last 7 Days from Yesterday”, “Last 14 Days”, “Last 30 Days”, “This Week”, “Last Week”, “This Month”, or “Last Month”.

Scope Required

read_orgs

Example Response

Response Code: 200

{
  "data": [
    {
      "grand_total": {
        "digital": <string: total coding activity in digital clock format>,
        "hours": <integer: hours portion of coding activity>,
        "minutes": <integer: minutes portion of coding activity>,
        "text": <string: total coding activity in human readable format>,
        "total_seconds": <float: total coding activity as seconds>
      },
      "projects": [
        {
          "name": <string: project name>,
          "total_seconds": <float: total coding activity as seconds>,
          "percent": <float: percent of time spent in this project>,
          "digital": <string: total coding activity for this project in digital clock format>,
          "text": <string: total coding activity in human readable format>,
          "hours": <integer: hours portion of coding activity for this project>,
          "minutes": <integer: minutes portion of coding activity for this project>
        }, …
      ],
      "languages": [
        {
          "name": <string: language name>,
          "total_seconds": <float: total coding activity spent in this language as seconds>,
          "percent": <float: percent of time spent in this language>,
          "digital": <string: total coding activity for this language in digital clock format>,
          "text": <string: total coding activity in human readable format>,
          "hours": <integer: hours portion of coding activity for this language>,
          "minutes": <integer: minutes portion of coding activity for this language>,
          "seconds": <integer: seconds portion of coding activity for this language>
        }, …
      ],
      "editors": [
        {
          "name": <string: editor name>,
          "total_seconds": <float: total coding activity spent in this editor as seconds>,
          "percent": <float: percent of time spent in this editor>,
          "digital": <string: total coding activity for this editor in digital clock format>,
          "text": <string: total coding activity in human readable format>,
          "hours": <integer: hours portion of coding activity for this editor>,
          "minutes": <integer: minutes portion of coding activity for this editor>,
          "seconds": <integer: seconds portion of coding activity for this editor>
        }, …
      ],
      "operating_systems": [
        {
          "name": <string: os name>,
          "total_seconds": <float: total coding activity spent in this os as seconds>,
          "percent": <float: percent of time spent in this os>,
          "digital": <string: total coding activity for this os in digital clock format>,
          "text": <string: total coding activity in human readable format>,
          "hours": <integer: hours portion of coding activity for this os>,
          "minutes": <integer: minutes portion of coding activity for this os>,
          "seconds": <integer: seconds portion of coding activity for this os>
        }, …
      ],
      "branches": [ // included only when project url parameter used
        {
          "name": <string: branch name>,
          "total_seconds": <float: total coding activity spent in this branch as seconds>,
          "percent": <float: percent of time spent in this branch>,
          "digital": <string: total coding activity for this branch in digital clock format>,
          "text": <string: total coding activity in human readable format>,
          "hours": <integer: hours portion of coding activity for this branch>,
          "minutes": <integer: minutes portion of coding activity for this branch>,
          "seconds": <integer: seconds portion of coding activity for this branch>
        }, …
      ],
      "entities": [ // included only when project url parameter used
        {
          "name": <string: entity name>,
          "total_seconds": <float: total coding activity spent in this entity as seconds>,
          "percent": <float: percent of time spent in this entity>,
          "digital": <string: total coding activity for this entity in digital clock format>,
          "text": <string: total coding activity in human readable format>,
          "hours": <integer: hours portion of coding activity for this entity>,
          "minutes": <integer: minutes portion of coding activity for this entity>,
          "seconds": <integer: seconds portion of coding activity for this entity>
        }, …
      ],
      "range": {
        "date": <string: this day as Date string in YEAR-MONTH-DAY format>,
        "start": <string: start of this day as ISO 8601 UTC datetime>,
        "end": <string: end of this day as ISO 8601 UTC datetime>,
        "text": <string: this day in human-readable format relative to the current day>,
        "timezone": <string: timezone used in Olson Country/Region format>
      }
    }, …
  ],
  "start": <string: start of time range as ISO 8601 UTC datetime>,
  "end": <string: end of time range as ISO 8601 UTC datetime>,
}

Org Dashboard Members

GET /api/v1/users/:user/orgs/:org/dashboards/:dashboard/members

GET /api/v1/users/current/orgs/:org/dashboards/:dashboard/members

Description

List an organization’s members.

Scope Required

read_orgs

Example Response

Response Code: 200

{
  "data": [
    {
      "id": <string: unique id of user>,
      "email": <string: email address>,
      "full_name": <string: full name of user>,
      "is_view_only": <boolean: when true, this member’s coding activity is hidden from the dashboard>,
      "photo": <string: url of photo for this user>,
      "username": <string: users public username>,
    }, …
  ],
  "next_page": <integer: the next page number, if available>,
  "page": <integer: the current page number>,
  "prev_page": <integer: the previous page number, if available>,
  "total": <integer: total number of dashboard members>,
  "total_pages": <integer: number of pages available>,
}

Org Dashboards

GET /api/v1/users/:user/orgs/:org/dashboards

GET /api/v1/users/current/orgs/:org/dashboards

Description

List the organization’s dashboards.

Scope Required

read_orgs

Example Response

Response Code: 200

{
  "data": [
    {
      "id": <string: unique id of this dashboard>,
      "full_name": <string: this dashboard’s name>,
      "created_by": <string: name of user who created this dashboard>,
      "timezone": <string: the dashboard's timezone in Olson Country/Region format; defaults to the organization’s timezone>,
      "has_changed_timezone": <boolean: whether this dashboard’s timezone is different from the organization’s timezone preference>,
      "members_count": <integer: total number of members in this dashboard>,
      "members_count_human_readable": <string: number of members in this dashboard as string>,
      "is_current_user_member": <boolean: whether the currently authenticated user is a member of this dashboard>,
      "can_current_user_view": <boolean: whether the currently authenticated user can view this dashboard>,
      "can_current_user_request_to_view": <boolean: whether the currently authenticated user can request to view this dashboard>,
      "can_current_user_request_to_join": <boolean: whether the currently authenticated user can request to join this dashboard>,
      "can_current_user_add_members": <boolean: whether the currently authenticated user can add members to this dashboard>,
      "can_current_user_remove_members": <boolean: whether the currently authenticated user can remove members from this dashboard>,
      "can_current_user_delete": <boolean: whether the currently authenticated user can delete this dashboard>,
      "created_at": <string: time when user was created in ISO 8601 format>,
      "modified_at": <string: time when user was last modified in ISO 8601 format>,
    }, …
  ],
  "next_page": <integer: the next page number, if available>,
  "page": <integer: the current page number>,
  "prev_page": <integer: the previous page number, if available>,
  "total": <integer: total number of dashboards in this org>,
  "total_pages": <integer: number of pages available>,
}

Orgs

GET /api/v1/users/:user/orgs

GET /api/v1/users/current/orgs

Description

List a user’s organizations.

Scope Required

read_orgs

Example Response

Response Code: 200

{
  "data": [
    {
      "id": <string: unique id of org>,
      "name": <string: the org’s name.>,
      "default_project_privacy": <string: the user’s default privacy for projects on dashboards; can be "visible" or "hidden">,
      "invited_people_count": <integer: number of pending invites>,
      "invited_people_count_human_readable": <string: number of pending invites as string>,
      "is_duration_visible": <boolean: when true, people in this org can see each other’s durations coding activity>,
      "people_count": <integer: number of people in this org>,
      "people_count_human_readable": <string: number of people in this org as string>,
      "timeout": <integer: this organization’s timeout preference>,
      "timezone": <integer: this organization’s timezone preference>,
      "writes_only": <integer: this organization’s writes-only preference>
      "can_current_user_list_dashboards": <boolean: whether the currently authenticated user can list dashboards>,
      "can_current_user_create_dashboards": <boolean: whether the currently authenticated user can create dashboards>,
      "can_current_user_display_coding_on_dashboards": <boolean: whether the currently authenticated user can display their coding activity on dashboards>,
      "can_current_user_view_all_dashboards": <boolean: whether the currently authenticated user can view dashboards in this org without first being invited>,
      "can_current_user_add_people_to_dashboards": <boolean: whether the currently authenticated user can add people to dashboards>,
      "can_current_user_remove_people_from_dashboards": <boolean: whether the currently authenticated user can remove people from dashboards>,
      "can_current_user_edit_and_delete_dashboards": <boolean: whether the currently authenticated user can edit and delete dashboards>,
      "can_current_user_add_people_to_org": <boolean: whether the currently authenticated user can add people to this org>,
      "can_current_user_remove_people_from_org": <boolean: whether the currently authenticated user can remove people from this org>,
      "can_current_user_manage_groups": <boolean: whether the currently authenticated user can add, manage, and delete groups and permissions>,
      "can_current_user_view_audit_log": <boolean: whether the currently authenticated user can view the org’s audit log>,
      "can_current_user_edit_org": <boolean: whether the currently authenticated user can edit this org’s preferences>,
      "can_current_user_manage_billing": <boolean: whether the currently authenticated user can manage this org’s billing>,
      "can_current_user_delete_org": <boolean: whether the currently authenticated user can delete this org>,
      "created_at": <string: time when user was created in ISO 8601 format>,
      "modified_at": <string: time when user was last modified in ISO 8601 format>,
    }, …
  ],
  "next_page": <integer: the next page number, if available>,
  "page": <integer: the current page number>,
  "prev_page": <integer: the previous page number, if available>,
  "total": <integer: total number of orgs>,
  "total_pages": <integer: number of pages available>,
}

Private Leaderboards

GET /api/v1/users/:user/leaderboards

GET /api/v1/users/current/leaderboards

Description

List user’s private leaderboards. Same as this page.

Scope Required

read_private_leaderboards

Example Response

Response Code: 200

{
  "data": [
    {
      "can_delete": <boolean: true if user has access to delete this leaderboard>,
      "can_edit": <boolean: true if user has access to edit this leaderboard>,
      "created_at": <string: time when leaderboard was created in ISO 8601 format>,
      "has_available_seat": <boolean: true if this leaderboard has room for more members>,
      "id": <string: unique id of leaderboard>,
      "members_count": <int: number of members in this private leaderboard>,
      "members_with_timezones_count": <int: number of members who have timezones set; when a user does not have a timezone, they will be hidden from leaderboards>,
      "modified_at": <string: time when leaderboard was last modified in ISO 8601 format>,
      "name": <string: display name>,
      "time_range": <string: time range of this leaderboard; always "last_7_days">,
    }, …
  ],
  "total": <integer: total number of private leaderboards>,
  "total_pages": <integer: number of pages available>,
}

Try it out

Private Leaderboards Leaders

GET /api/v1/users/:user/leaderboards/:board

GET /api/v1/users/current/leaderboards/:board

Description

List of users in this private leaderboard ranked by coding activity in descending order.

URL Parameters

language - String - optional - Filter leaders by a specific language.

page - Integer - optional - Page number of leaderboard.

Scope Required

read_private_leaderboards

Example Response

Response Code: 200

{
  "data": [
    {
      "rank": <int: rank of this leaderboard member>,
      "running_total": {
        "total_seconds": <float: total coding activity for this user as seconds>,
        "human_readable_total": <string: total coding activity for this user as human readable string>,
        "daily_average": <float: daily average for this user as seconds>,
        "human_readable_daily_average": <string: daily average for this user as human readable string>,
        "languages": [
          {
            "name": <string: language name>,
            "total_seconds": <float: total seconds user has logged in this language>,
          }, …
        ],
      },
      "user": {
        "id": <string: unique id of user>,
        "email": <string: email address of user, if public>,
        "username": <string: users public username>,
        "full_name": <string: full name of user>,
        "display_name": <string: display name of this user taken from full_name or @username. Defaults to 'Anonymous User'>,
        "website": <string: website of user>,
        "human_readable_website": <string: website of user without url scheme>,
        "location": <string: location of user>,
        "is_email_public": <boolean: whether this user's email should be shown publicly on leader boards>,
        "photo_public": <boolean: whether this user's photo should be shown publicly on leader boards>,
      },
    }, …
  ],
  "language": <integer: total number of private leaderboards>,
  "modified_at": <string: time when leaderboard was last modified in ISO 8601 format>,
  "page": <int: current page>,
  "range": {
    "start_date": <string: start of this range as ISO 8601 UTC datetime>,
    "start_text": <string: start of range in human-readable format relative to the current day>,
    "end_date": <string: end of range as ISO 8601 UTC datetime>,
    "end_text": <string: end of range in human-readable format relative to the current day>,
    "name": <string: time range of this leaderboard>,
    "text": <string: time range in human-readable format relative to the current day>,
  }
  "timeout": <integer: timeout setting in minutes used by this leaderboard>,
  "total_pages": <integer: number of pages available>,
  "writes_only": <boolean: writes_only setting used by this leaderboard>,
}

Projects

GET /api/v1/users/:user/projects

GET /api/v1/users/current/projects

Description

List of WakaTime projects for the current user.

URL Parameters

q - String - optional - Filter project names by a search term.

Scope Required

read_logged_time

Example Response

Response Code: 200

{
  "data": [
    {
      "id": <string: unique project id>,
      "name": <string: project name>,
      "repository": <string: associated repository if connected>,
    }, …
  ],
}

Stats

GET /api/v1/users/:user/stats/:range

GET /api/v1/users/current/stats/:range

Description

A user's coding activity for the given time range. range can be one of last_7_days, last_30_days, last_6_months, or last_year. For accounts subscribed to the free plan, time ranges >= one year are updated on the first request. It’s best to always check is_up_to_date and retry your request when the response is stale. Stats are read-only representations of Heartbeats, Durations, and Summaries, created by joining multiple Heartbeats together when they’re within 15 minutes of each other. The 15 minutes default can be changed with your account’s Timeout preference.

URL Parameters

timeout - Integer - optional - The timeout value used to calculate these stats. Defaults the the user's timeout value.

writes_only - Boolean - optional - The writes_only value used to calculate these stats. Defaults to the user's writes_only setting.

project - String - optional - Show more detailed stats limited to this project.

Scope Required

read_stats

Example Response

Response Code: 200

{
  "data": {
    "total_seconds": <float: total coding activity as seconds for the given range of time>,
    "human_readable_total": <string: total coding activity as human readable string>,
    "daily_average": <float: average coding activity per day as seconds for the given range of time>,
    "human_readable_daily_average": <string: daily average as human readable string>,
    "projects": [
      {
        "name": <string: project name>,
        "total_seconds": <float: total coding activity as seconds>,
        "percent": <float: percent of time spent in this project>,
        "digital": <string: total coding activity for this project in digital clock format>,
        "text": <string: total coding activity in human readable format>,
        "hours": <integer: hours portion of coding activity for this project>,
        "minutes": <integer: minutes portion of coding activity for this project>
      }, …
    ],
    "languages": [
      {
        "name": <string: language name>,
        "total_seconds": <float: total coding activity spent in this language as seconds>,
        "percent": <float: percent of time spent in this language>,
        "digital": <string: total coding activity for this language in digital clock format>,
        "text": <string: total coding activity in human readable format>,
        "hours": <integer: hours portion of coding activity for this language>,
        "minutes": <integer: minutes portion of coding activity for this language>,
        "seconds": <integer: seconds portion of coding activity for this language>
      }, …
    ],
    "editors": [
      {
        "name": <string: editor name>,
        "total_seconds": <float: total coding activity spent in this editor as seconds>,
        "percent": <float: percent of time spent in this editor>,
        "digital": <string: total coding activity for this editor in digital clock format>,
        "text": <string: total coding activity in human readable format>,
        "hours": <integer: hours portion of coding activity for this editor>,
        "minutes": <integer: minutes portion of coding activity for this editor>,
        "seconds": <integer: seconds portion of coding activity for this editor>
      }, …
    ],
    "operating_systems": [
      {
        "name": <string: os name>,
        "total_seconds": <float: total coding activity spent in this os as seconds>,
        "percent": <float: percent of time spent in this os>,
        "digital": <string: total coding activity for this os in digital clock format>,
        "text": <string: total coding activity in human readable format>,
        "hours": <integer: hours portion of coding activity for this os>,
        "minutes": <integer: minutes portion of coding activity for this os>,
        "seconds": <integer: seconds portion of coding activity for this os>
      }, …
    ],
    "dependencies": [
      {
        "name": <string: dependency name>,
        "total_seconds": <float: total coding activity spent in this dependency as seconds>,
        "percent": <float: percent of time spent in this dependency>,
        "digital": <string: total coding activity for this dependency in digital clock format>,
        "text": <string: total coding activity in human readable format>,
        "hours": <integer: hours portion of coding activity for this dependency>,
        "minutes": <integer: minutes portion of coding activity for this dependency>,
        "seconds": <integer: seconds portion of coding activity for this dependency>
      }, …
    ],
    "machines": [
      {
        "name": <string: machine hostname and ip address>,
        "machine_name_id": <string: unique id of this machine>,
        "total_seconds": <float: total coding activity spent on this machine as seconds>,
        "percent": <float: percent of time spent on this machine>,
        "digital": <string: total coding activity for this machine in digital clock format>,
        "text": <string: total coding activity in human readable format>,
        "hours": <integer: hours portion of coding activity for this machine>,
        "minutes": <integer: minutes portion of coding activity for this machine>,
        "seconds": <integer: seconds portion of coding activity for this machine>
      }, …
    ],
    "best_day": {
      "date": <string: day with most coding time logged as Date string in YEAR-MONTH-DAY format>,
      "text": <string: total coding activity for this day in human readable format>,
      "total_seconds": <float: number of seconds of coding activity for this day>
    },
    "range": <string: time range of these stats>,
    "holidays": <integer: number of days in this range with no coding time logged>,
    "days_including_holidays": <integer: number of days in this range>,
    "days_minus_holidays": <integer: number of days in this range excluding days with no coding time logged>,
    "status": <string: status of these stats in the cache>,
    "is_already_updating": <boolean: true if these stats are being updated in the background>,
    "is_coding_activity_visible": <boolean: true if this user's coding activity is publicly visible>,
    "is_other_usage_visible": <boolean: true if this user's languages, editors, and operating system stats are publicly visible>,
    "is_stuck": <boolean: true if these stats got stuck while processing and will be recalculated in the background>,
    "is_including_today": <boolean: true if these stats include the current day; normally false except range "all_time">,
    "is_up_to_date": <boolean: true if these stats are up to date; when false, stats are missing or from an old time range and will be refreshed soon>,
    "start": <string: start of this time range as ISO 8601 UTC datetime>,
    "end": <string: end of this time range as ISO 8601 UTC datetime>,
    "timezone": <string: timezone used in Olson Country/Region format>,
    "timeout": <integer: value of the user's timeout setting in minutes>,
    "writes_only": <boolean: status of the user's writes_only setting>,
    "user_id": <string: unique id of this user>,
    "username": <string: public username for this user>,
    "created_at": <string: time when these stats were created in ISO 8601 format>,
    "modified_at": <string: time when these stats were last updated in ISO 8601 format>
  }
}

Stats Aggregated

GET /api/v1/stats/:range

Description

Aggregate stats of all WakaTime users over the given time range. range can be one of last_7_days or any year in the past since 2013 for ex: 2020. Aggregate stats are only available with the same preferences as public profiles (Default 15m timeout preference). Yearly aggregate stats are calculated each year on Jan 1st.

Example Response

Response Code: 200

{
  "data": {
    "categories": [
      {
        "name": <string: name of this category, for ex: Coding or Debugging>,
        "is_verified": <boolean: whether the category of activity is verified or unverified>,
        "average": {
          "seconds": <float: average number of seconds coded by all WakaTime users in this category>,
          "text": <string: average time coded by all WakaTime users in this category as a human readable string>,
        },
        "count": {
          "text": <string: number of WakaTime users who coded in this category in the given range>,
        },
        "max": {
          "seconds": <float: number of seconds coded by the WakaTime user who coded the most time in this category>,
          "text": <string: time coded by the WakaTime user who coded the most time in this category>,
        },
        "median": {
          "seconds": <float: median number of seconds coded by all WakaTime users in this category>,
          "text": <string: median time coded by all WakaTime users in this category as a human readable string>,
        },
        "sum": {
          "seconds": <float: sum of all seconds coded by all WakaTime users in this category>,
          "text": <string: sum of all time coded by all WakaTime users in this category as a human readable string>,
        },
      }, …
    ],
    "daily_average": {
      "average": {
        "seconds": <float: average number of seconds coded per day by all WakaTime users in given range>,
        "text": <string: average time coded per day by all WakaTime users in given range as a human readable string>,
      },
      "count": {
        "text": <string: number of WakaTime users in these aggregate stats>,
      },
      "max": {
        "seconds": <float: number of seconds coded per day by the WakaTime user who coded the most time in the given range; this might not be the highest daily average, for ex: a user codes for 23h one day but then stops coding. That user’s daily average is 23h. The user with the most code time has a daily average of 12h. The max is 12h not 23h, because the user with 12h daily average coded more days and more total time than the user with 23h daily average.>,
        "text": <string: daily average as human readable text of the WakaTime user who coded the most time in the given range>,
      },
      "median": {
        "seconds": <float: median number of seconds coded per day by all WakaTime users in given range>,
        "text": <string: median time coded per day by all WakaTime users in given range as a human readable string>,
      },
    },
    "editors": [
      {
        "name": <string: name of this IDE, for ex: Coding or Debugging>,
        "is_verified": <boolean: whether the IDE is verified or unverified>,
        "average": {
          "seconds": <float: average number of seconds coded by all WakaTime users with this IDE>,
          "text": <string: average time coded by all WakaTime users with this IDE as a human readable string>,
        },
        "count": {
          "text": <string: number of WakaTime users who coded with this IDE in the given range>,
        },
        "max": {
          "seconds": <float: number of seconds coded by the WakaTime user who coded the most time with this IDE>,
          "text": <string: time coded by the WakaTime user who coded the most time with this IDE>,
        },
        "median": {
          "seconds": <float: median number of seconds coded by all WakaTime users with this IDE>,
          "text": <string: median time coded by all WakaTime users with this IDE as a human readable string>,
        },
        "sum": {
          "seconds": <float: sum of all seconds coded by all WakaTime users with this IDE>,
          "text": <string: sum of all time coded by all WakaTime users with this IDE as a human readable string>,
        },
      }, …
    ],
    "languages": [
      {
        "name": <string: name of this language, for ex: Coding or Debugging>,
        "is_verified": <boolean: whether the language is verified or unverified>,
        "average": {
          "seconds": <float: average number of seconds coded by all WakaTime users in this language>,
          "text": <string: average time coded by all WakaTime users in this language as a human readable string>,
        },
        "count": {
          "text": <string: number of WakaTime users who coded in this language in the given range>,
        },
        "max": {
          "seconds": <float: number of seconds coded by the WakaTime user who coded the most time in this language>,
          "text": <string: time coded by the WakaTime user who coded the most time in this language>,
        },
        "median": {
          "seconds": <float: median number of seconds coded by all WakaTime users in this language>,
          "text": <string: median time coded by all WakaTime users in this language as a human readable string>,
        },
        "sum": {
          "seconds": <float: sum of all seconds coded by all WakaTime users in this language>,
          "text": <string: sum of all time coded by all WakaTime users in this language as a human readable string>,
        },
      }, …
    ],
    "operating_systems": [
      {
        "name": <string: name of this os, for ex: Coding or Debugging>,
        "is_verified": <boolean: whether the os is verified or unverified>,
        "average": {
          "seconds": <float: average number of seconds coded by all WakaTime users in this os>,
          "text": <string: average time coded by all WakaTime users in this os as a human readable string>,
        },
        "count": {
          "text": <string: number of WakaTime users who coded in this os in the given range>,
        },
        "max": {
          "seconds": <float: number of seconds coded by the WakaTime user who coded the most time in this os>,
          "text": <string: time coded by the WakaTime user who coded the most time in this os>,
        },
        "median": {
          "seconds": <float: median number of seconds coded by all WakaTime users in this os>,
          "text": <string: median time coded by all WakaTime users in this os as a human readable string>,
        },
        "sum": {
          "seconds": <float: sum of all seconds coded by all WakaTime users in this os>,
          "text": <string: sum of all time coded by all WakaTime users in this os as a human readable string>,
        },
      }, …
    ],
    "total": {
      "average": {
        "seconds": <float: average number of seconds coded by all WakaTime users in given range>,
        "text": <string: average time coded by all WakaTime users in given range as a human readable string>,
      },
      "count": {
        "text": <string: number of WakaTime users in these aggregate stats>,
      },
      "max": {
        "seconds": <float: number of seconds coded by the WakaTime user who coded the most time in the given range>,
        "text": <string: time coded by the WakaTime user who coded the most time in the given range>,
      },
      "median": {
        "seconds": <float: median number of seconds coded by all WakaTime users in given range>,
        "text": <string: median time coded by all WakaTime users in given range as a human readable string>,
      },
      "sum": {
        "seconds": <float: sum of all seconds coded by all WakaTime users in given range>,
        "text": <string: sum of all time coded by all WakaTime users in given range as a human readable string>,
      },
    },
    "range": {
      "end_date": <string: end of range as human readable date>,
      "end_text": <string: end of range as ISO 8601 UTC datetime>,
      "name": <string: range of these stats>,
      "start_date": <string: start of range as human readable date>,
      "start_text": <string: start of range as ISO 8601 UTC datetime>,
      "text": <string: range in human-readable format>,
    },
    "timeout": <integer: the default Timeout Preference for public stats (15)>,
    "writes_only": <boolean: the default Writes Only Preference for public stats (false)>,
  }
}

Try it out

Summaries

GET /api/v1/users/:user/summaries

GET /api/v1/users/current/summaries

Description

A user's coding activity for the given time range as an array of summaries segmented by day. Summaries are read-only representations of Heartbeats and Durations, created by joining multiple Heartbeats together when they’re within 15 minutes of each other. The 15 minutes default can be changed with your account’s Timeout preference.

URL Parameters

start - Date - required - Start date of the time range.

end - Date - required - End date of the time range.

project - String - optional - Only show time logged to this project.

branches - String - optional - Only show coding activity for these branches; comma separated list of branch names.

timeout - Integer - optional - The timeout preference used when joining heartbeats into durations. Defaults the the user's timeout value. See the FAQ for more info.

writes_only - Boolean - optional - The writes_only preference. Defaults to the user's writes_only setting.

timezone - String - optional - The timezone for given start and end dates. Defaults to the user's timezone.

range - String - optional - Alternative way to supply start and end dates. Can be one of “Today”, “Yesterday”, “Last 7 Days”, “Last 7 Days from Yesterday”, “Last 14 Days”, “Last 30 Days”, “This Week”, “Last Week”, “This Month”, or “Last Month”.

Scope Required

read_logged_time

Example Response

Response Code: 200

{
  "data": [
    {
      "grand_total": {
        "digital": <string: total coding activity in digital clock format>,
        "hours": <integer: hours portion of coding activity>,
        "minutes": <integer: minutes portion of coding activity>,
        "text": <string: total coding activity in human readable format>,
        "total_seconds": <float: total coding activity as seconds>
      },
      "projects": [
        {
          "name": <string: project name>,
          "total_seconds": <float: total coding activity as seconds>,
          "percent": <float: percent of time spent in this project>,
          "digital": <string: total coding activity for this project in digital clock format>,
          "text": <string: total coding activity in human readable format>,
          "hours": <integer: hours portion of coding activity for this project>,
          "minutes": <integer: minutes portion of coding activity for this project>
        }, …
      ],
      "languages": [
        {
          "name": <string: language name>,
          "total_seconds": <float: total coding activity spent in this language as seconds>,
          "percent": <float: percent of time spent in this language>,
          "digital": <string: total coding activity for this language in digital clock format>,
          "text": <string: total coding activity in human readable format>,
          "hours": <integer: hours portion of coding activity for this language>,
          "minutes": <integer: minutes portion of coding activity for this language>,
          "seconds": <integer: seconds portion of coding activity for this language>
        }, …
      ],
      "editors": [
        {
          "name": <string: editor name>,
          "total_seconds": <float: total coding activity spent in this editor as seconds>,
          "percent": <float: percent of time spent in this editor>,
          "digital": <string: total coding activity for this editor in digital clock format>,
          "text": <string: total coding activity in human readable format>,
          "hours": <integer: hours portion of coding activity for this editor>,
          "minutes": <integer: minutes portion of coding activity for this editor>,
          "seconds": <integer: seconds portion of coding activity for this editor>
        }, …
      ],
      "operating_systems": [
        {
          "name": <string: os name>,
          "total_seconds": <float: total coding activity spent in this os as seconds>,
          "percent": <float: percent of time spent in this os>,
          "digital": <string: total coding activity for this os in digital clock format>,
          "text": <string: total coding activity in human readable format>,
          "hours": <integer: hours portion of coding activity for this os>,
          "minutes": <integer: minutes portion of coding activity for this os>,
          "seconds": <integer: seconds portion of coding activity for this os>
        }, …
      ],
      "dependencies": [
        {
          "name": <string: dependency name>,
          "total_seconds": <float: total coding activity spent in this dependency as seconds>,
          "percent": <float: percent of time spent in this dependency>,
          "digital": <string: total coding activity for this dependency in digital clock format>,
          "text": <string: total coding activity in human readable format>,
          "hours": <integer: hours portion of coding activity for this dependency>,
          "minutes": <integer: minutes portion of coding activity for this dependency>,
          "seconds": <integer: seconds portion of coding activity for this dependency>
        }, …
      ],
      "machines": [
        {
          "name": <string: machine hostname and ip address>,
          "machine_name_id": <string: unique id of this machine>,
          "total_seconds": <float: total coding activity spent on this machine as seconds>,
          "percent": <float: percent of time spent on this machine>,
          "digital": <string: total coding activity for this machine in digital clock format>,
          "text": <string: total coding activity in human readable format>,
          "hours": <integer: hours portion of coding activity for this machine>,
          "minutes": <integer: minutes portion of coding activity for this machine>,
          "seconds": <integer: seconds portion of coding activity for this machine>
        }, …
      ],
      "branches": [ // included only when project url parameter used
        {
          "name": <string: branch name>,
          "total_seconds": <float: total coding activity spent in this branch as seconds>,
          "percent": <float: percent of time spent in this branch>,
          "digital": <string: total coding activity for this branch in digital clock format>,
          "text": <string: total coding activity in human readable format>,
          "hours": <integer: hours portion of coding activity for this branch>,
          "minutes": <integer: minutes portion of coding activity for this branch>,
          "seconds": <integer: seconds portion of coding activity for this branch>
        }, …
      ],
      "entities": [ // included only when project url parameter used
        {
          "name": <string: entity name>,
          "total_seconds": <float: total coding activity spent in this entity as seconds>,
          "percent": <float: percent of time spent in this entity>,
          "digital": <string: total coding activity for this entity in digital clock format>,
          "text": <string: total coding activity in human readable format>,
          "hours": <integer: hours portion of coding activity for this entity>,
          "minutes": <integer: minutes portion of coding activity for this entity>,
          "seconds": <integer: seconds portion of coding activity for this entity>
        }, …
      ],
      "range": {
        "date": <string: this day as Date string in YEAR-MONTH-DAY format>,
        "start": <string: start of this day as ISO 8601 UTC datetime>,
        "end": <string: end of this day as ISO 8601 UTC datetime>,
        "text": <string: this day in human-readable format relative to the current day>,
        "timezone": <string: timezone used in Olson Country/Region format>
      }
    }, …
  ],
  "cummulative_total": {
    "seconds": <float: cummulative number of seconds over the date range of summaries>,
    "text": <string: cummulative total coding activity in human readable format>,
  },
  "start": <string: start of time range as ISO 8601 UTC datetime>,
  "end": <string: end of time range as ISO 8601 UTC datetime>,
}

User Agents

GET /api/v1/users/:user/user_agents

GET /api/v1/users/current/user_agents

Description

List of plugins which have sent data for this user.

Scope Required

read_logged_time

Example Response

Response Code: 200

{
  "data": {
    "id": <string: unique id of this user agent>,
    "value": <string: a user agent string>,
    "editor": <string: the editor/IDE name of this user agent>,
    "version": <string: the wakatime plugin version of this user agent>,
    "os": <string: operating system of this user agent>,
    "last_seen_at": <string: time when this user agent was last seen in ISO 8601 format>,
    "created_at": <string: time when this user agent was first seen in ISO 8601 format>,
  },
}

Users

GET /api/v1/users/:user

GET /api/v1/users/current

Description

A single user.

Scope Required

email

Example Response

Response Code: 200

{
  "data": {
    "id": <string: unique id of user>,
    "has_premium_features": <boolean: true if user has access to premium features>,
    "display_name": <string: display name of this user taken from full_name or @username. Defaults to 'Anonymous User'>,
    "full_name": <string: full name of user>,
    "email": <string: email address>,
    "photo": <string: url of photo for this user>,
    "is_email_public": <boolean: whether this user's email should be shown on the public leader board>,
    "is_email_confirmed": <boolean: whether this user's email address has been verified with a confirmation email>,
    "public_email": <string: email address for public profile. Nullable.>,
    "photo_public": <boolean: whether this user's photo should be shown on the public leader board>,
    "timezone": <string: user's timezone in Olson Country/Region format>,
    "last_heartbeat_at": <string: time of most recent heartbeat received in ISO 8601 format>,
    "last_plugin": <string: user-agent string from the last plugin used>,
    "last_plugin_name": <string: name of editor last used>,
    "last_project": <string: name of last project coded in>,
    "plan": <string: users subscription plan>,
    "username": <string: users public username>,
    "website": <string: website of user>,
    "human_readable_website": <string: website of user without protocol part>,
    "location": <string: location of user>,
    "logged_time_public": <boolean: coding activity should be shown on the public leader board>,
    "languages_used_public": <boolean: languages used should be shown on the public leader board>,
    "is_hireable": <boolean: user preference showing hireable badge on public profile>,
    "created_at": <string: time when user was created in ISO 8601 format>,
    "modified_at": <string: time when user was last modified in ISO 8601 format>,
  },
}