NAV
API Reference
Shell Ruby Python JavaScript

Introduction

About TimelyDo

TimelyDo is a scheduling platform. You publish a booking page, share the link, and people pick a time from your real availability. No back and forth emails, and no double bookings.

TimelyDo syncs with Google Calendar, so events already on your calendar block those time slots. It connects to Zoom and Google Meet for the meetings people book with you. Accounts are personal, and organizations can group members together.

Using TimelyDo is free. Learn more on the features pages or in the Help Center.

About the API

The TimelyDo API lets you work with your TimelyDo account from your own applications, scripts and integrations. It uses the same data you see in the app, so anything you read or change through the API shows up in TimelyDo straight away.

Need help? Email support@timelydo.com.

Every example on this page comes in Shell (curl), Ruby, Python and JavaScript. Switch languages with the tabs at the top right.

Base URL

All endpoints live under:

https://timelydo.com/api/v1

Response format

Every response, success or failure, has the same shape:

{
  "success": true,
  "message": "user details",
  "data": {},
  "status": 200
}

Requests and responses are JSON. Every response carries the same four fields:

Field Type Description
success boolean true when the request worked, false otherwise.
message string A short human readable description of the result.
data object or array The payload. An empty object when there is nothing to return.
status integer or string Mirrors the HTTP status. Successful responses use the number (200). Errors use the status name ("unauthorized", "forbidden").

Always check the HTTP status code or success before reading data.

Authentication

The TimelyDo API uses API keys. Every request must send your key in the X-API-KEY header. Requests without a valid key are rejected with 401 Unauthorized.

Get your API key

Every TimelyDo account has one API key, created when the account is created. To find it:

  1. Sign in at timelydo.com.
  2. Open Settings, then Developers Console, then API Key. You can also go straight to timelydo.com/settings/developers/api_key.
  3. Click the copy button next to Your API Key.

Keys are 73 characters long. They do not expire. A key keeps working until you regenerate it or delete your account.

The examples on this page read the key from an environment variable called TIMELYDO_API_KEY, so it never appears in your code:

export TIMELYDO_API_KEY="paste your key here"

Authenticate your requests

curl "https://timelydo.com/api/v1/user" \
  -H "X-API-KEY: $TIMELYDO_API_KEY" \
  -H "Accept: application/json"
require 'net/http'
require 'json'

uri = URI('https://timelydo.com/api/v1/user')

request = Net::HTTP::Get.new(uri)
request['X-API-KEY'] = ENV.fetch('TIMELYDO_API_KEY')
request['Accept'] = 'application/json'

response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(request)
end

body = JSON.parse(response.body)

if body['success']
  puts "Authenticated as #{body['data']['email']}"
else
  warn "#{response.code}: #{body['message']}"
end
import os
import requests

response = requests.get(
    "https://timelydo.com/api/v1/user",
    headers={
        "X-API-KEY": os.environ["TIMELYDO_API_KEY"],
        "Accept": "application/json",
    },
    timeout=10,
)

body = response.json()

if body["success"]:
    print("Authenticated as", body["data"]["email"])
else:
    print(f"{response.status_code}: {body['message']}")
// Node.js 18 or newer (built in fetch). Run this on your server, never in a browser.
async function getCurrentUser() {
  const response = await fetch("https://timelydo.com/api/v1/user", {
    headers: {
      "X-API-KEY": process.env.TIMELYDO_API_KEY,
      "Accept": "application/json",
    },
  });

  const body = await response.json();

  if (body.success) {
    console.log(`Authenticated as ${body.data.email}`);
  } else {
    console.error(`${response.status}: ${body.message}`);
  }
}

getCurrentUser();

A valid key returns the account it belongs to (trimmed):

{
  "success": true,
  "message": "user details",
  "data": {
    "id": "3f6c2a9e-8b1d-4c7a-9e21-5d0b7f4a1c33",
    "email": "jane@example.com",
    "full_name": "Jane Doe",
    "url": "jane",
    "avatar_name": "JD",
    "timezone": "Berlin",
    "date_timezone": "Europe/Berlin",
    "locale": "en",
    "time_format": "12_hours",
    "date_format": "31/12/2024",
    "currency": "eur",
    "country_iso_code": "de",
    "api_key": "YOUR_API_KEY",
    "created_at": "2026-08-09T04:23:16.260Z"
  },
  "status": 200
}

A missing or wrong key returns 401:

{
  "success": false,
  "message": "Invalid api_key",
  "data": {},
  "status": "unauthorized"
}

Send the key in the X-API-KEY header on every request:

X-API-KEY: YOUR_API_KEY

The header name is not case sensitive. The key itself must match exactly.

The quickest way to check a key is GET /api/v1/user. It returns the account the key belongs to.

HTTP Request

GET https://timelydo.com/api/v1/user

Authentication errors

HTTP status message Cause
401 api_key is missing No X-API-KEY header was sent.
401 Invalid api_key The key does not match any active account. It may have been regenerated, or the account was deleted.
403 depends on the endpoint The endpoint only works from a signed in browser session. See below.

Endpoints that need a signed in session

A few account security settings cannot be changed with an API key, even a valid one. This protects your account if a key ever leaks. These endpoints return 403 Forbidden for API key requests:

Endpoint 403 message
/api/v1/two_factor (all methods) and /api/v1/two_factor/backup_codes Sign in to the app to manage two factor authentication.
/api/v1/hellobar and its actions A signed in session is required

Manage these from the TimelyDo app instead.

Regenerate your API key

Regenerate your key if it may have leaked, or to rotate it on a schedule. The old key stops working immediately, so update every integration that uses it right away.

You can regenerate the key in two ways.

In the app

  1. Open Settings, then Developers Console, then API Key.
  2. Click Regenerate key.
  3. Copy the new key shown on the page.

With the API

curl -X PUT "https://timelydo.com/api/v1/users/regenerate_api_key" \
  -H "X-API-KEY: $TIMELYDO_API_KEY" \
  -H "Accept: application/json"
require 'net/http'
require 'json'

uri = URI('https://timelydo.com/api/v1/users/regenerate_api_key')

request = Net::HTTP::Put.new(uri)
request['X-API-KEY'] = ENV.fetch('TIMELYDO_API_KEY')
request['Accept'] = 'application/json'

response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(request)
end

body = JSON.parse(response.body)

if body['success']
  new_api_key = body['data']['api_key']
  # Save new_api_key somewhere safe now. The old key has already stopped working.
  puts "New key received (#{new_api_key.length} characters)"
else
  warn "#{response.code}: #{body['message']}"
end
import os
import requests

response = requests.put(
    "https://timelydo.com/api/v1/users/regenerate_api_key",
    headers={
        "X-API-KEY": os.environ["TIMELYDO_API_KEY"],
        "Accept": "application/json",
    },
    timeout=10,
)

body = response.json()

if body["success"]:
    new_api_key = body["data"]["api_key"]
    # Save new_api_key somewhere safe now. The old key has already stopped working.
    print(f"New key received ({len(new_api_key)} characters)")
else:
    print(f"{response.status_code}: {body['message']}")
// Node.js 18 or newer (built in fetch). Run this on your server, never in a browser.
async function regenerateApiKey() {
  const response = await fetch("https://timelydo.com/api/v1/users/regenerate_api_key", {
    method: "PUT",
    headers: {
      "X-API-KEY": process.env.TIMELYDO_API_KEY,
      "Accept": "application/json",
    },
  });

  const body = await response.json();

  if (body.success) {
    const newApiKey = body.data.api_key;
    // Save newApiKey somewhere safe now. The old key has already stopped working.
    console.log(`New key received (${newApiKey.length} characters)`);
  } else {
    console.error(`${response.status}: ${body.message}`);
  }
}

regenerateApiKey();

The response contains the new key:

{
  "success": true,
  "message": "api_key is updated",
  "data": {
    "api_key": "YOUR_NEW_API_KEY"
  },
  "status": 200
}

Authenticate this request with your current key. The response returns the new key, and from that moment only the new key works.

HTTP Request

PUT https://timelydo.com/api/v1/users/regenerate_api_key

This endpoint takes no parameters.

If you lost your key

You cannot get a key back through the API without a working key. Sign in to TimelyDo and copy it from the API Key page, or regenerate a new one there.

Errors

Errors use the same response shape as successful requests:

{
  "success": false,
  "message": "missing params",
  "data": {
    "user": ["profile_picture"]
  },
  "status": "bad_request"
}

When a request fails, success is false, message says what went wrong, and status holds the HTTP status name. For some errors data carries extra detail, such as the list of missing fields.

HTTP status status field Meaning
400 bad_request Required parameters are missing. data lists them, grouped by object.
401 unauthorized The X-API-KEY header is missing, or the key is not valid. See Authentication.
403 forbidden Your key is valid, but this endpoint only works from a signed in browser session.
404 not_found The endpoint does not exist (endpoint does not exists), or the record you asked for was not found.
422 unprocessable_entity The request was understood, but the values failed validation. message explains which ones.
500 internal_server_error Something went wrong on our side. Try again later. If it keeps happening, contact support.