{"_id":"550bfb5622ccb01700a7946d","createdAt":"2015-03-19T14:16:51.119Z","excerpt":"This page will help you get started with Timekit. You'll be up and running in a jiffy!","githubsync":"","isReference":true,"order":0,"project":"550ada512188a71900453199","sync_unique":"","user":"550ada38cd78a42300ddf508","body":"[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Welcome to Timekit\",\n  \"body\": \"We'd love to hear what you're building! Throw us an email at [yourfriends@timekit.io](mailto:yourfriends@timekit.io) or chat with us (Intercom, lower right corner) and let's help you get off the ground together.\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Getting started guides\",\n  \"body\": \"Make your first API calls and learn by example with our quickstart guides:\\n1) [Setup resources & calendars](doc:guide-connect-and-setup-google-user)\\n2) [Availability search & find time](doc:guide-find-time-book-appointment)\\n3) [Creating & managing bookings](doc:guide-bookings)\"\n}\n[/block]\nThe Timekit API is organized around [REST](http://en.wikipedia.org/wiki/Representational_State_Transfer). Our API is designed to follow common HTTP conventions including response codes to indicate both errors and successful requests. Standard HTTP verbs (GET, POST, PUT, DELETE) are used for all methods, no exceptions.\n\n[JSON](http://www.json.org/) will be returned in all responses from the API, including error messages.\n\n## Root endpoint, versions and protocol\n\nAll API calls should be made to `https://api.timekit.io/v2` (note the explicit versioning). The current public version of the API is **version 2** and is the only publicly supported version (calls to v1 will result in 404 Not Found). \n\nHTTP over TLS 1.2 is enforced for all calls, so non-secure calls will result in a 301 Moved Permanently pointing to the https URI.\n\n## CORS\n\nOur API is intended to be consumed both by browser clients (e.g. [SPA](http://en.wikipedia.org/wiki/Single-page_application)s) and servers and supports [cross-origin resource sharing](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing). As of right now, JSONP is not supported, but we'd love to hear from you if it's of interest.\n\n## Application context\n\nWe provide a simple mechanism for tracking and bucketing app developers usage of the API by \"tagging\" all requests with an app ID. Read more about the application context [here](doc:application-context)\nFor demo purposes in the documentation, this value is always set to \"back-to-the-future\", you cannot use this test-application yourself.\n\n## Uuid as ids\n\nAll ids used by Timekit are uuid. Uuid looks like this: **de305d54-75b4-431b-adb2-eb6b9e546014**\nRead more about uuids [here](https://en.wikipedia.org/wiki/Universally_unique_identifier)","link_external":false,"next":{"description":"","pages":[]},"slug":"getting-started","title":"Introduction","api":{"auth":"required","params":[],"results":{"codes":[]},"settings":"","url":""},"category":"550bfb5622ccb01700a7946a","hidden":false,"type":"basic","updates":[],"__v":53,"link_url":"","parentDoc":null,"version":"550bfb5522ccb01700a79469","childrenPages":[]}

Introduction

This page will help you get started with Timekit. You'll be up and running in a jiffy!

[block:callout] { "type": "success", "title": "Welcome to Timekit", "body": "We'd love to hear what you're building! Throw us an email at [yourfriends@timekit.io](mailto:yourfriends@timekit.io) or chat with us (Intercom, lower right corner) and let's help you get off the ground together." } [/block] [block:callout] { "type": "info", "title": "Getting started guides", "body": "Make your first API calls and learn by example with our quickstart guides:\n1) [Setup resources & calendars](doc:guide-connect-and-setup-google-user)\n2) [Availability search & find time](doc:guide-find-time-book-appointment)\n3) [Creating & managing bookings](doc:guide-bookings)" } [/block] The Timekit API is organized around [REST](http://en.wikipedia.org/wiki/Representational_State_Transfer). Our API is designed to follow common HTTP conventions including response codes to indicate both errors and successful requests. Standard HTTP verbs (GET, POST, PUT, DELETE) are used for all methods, no exceptions. [JSON](http://www.json.org/) will be returned in all responses from the API, including error messages. ## Root endpoint, versions and protocol All API calls should be made to `https://api.timekit.io/v2` (note the explicit versioning). The current public version of the API is **version 2** and is the only publicly supported version (calls to v1 will result in 404 Not Found). HTTP over TLS 1.2 is enforced for all calls, so non-secure calls will result in a 301 Moved Permanently pointing to the https URI. ## CORS Our API is intended to be consumed both by browser clients (e.g. [SPA](http://en.wikipedia.org/wiki/Single-page_application)s) and servers and supports [cross-origin resource sharing](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing). As of right now, JSONP is not supported, but we'd love to hear from you if it's of interest. ## Application context We provide a simple mechanism for tracking and bucketing app developers usage of the API by "tagging" all requests with an app ID. Read more about the application context [here](doc:application-context) For demo purposes in the documentation, this value is always set to "back-to-the-future", you cannot use this test-application yourself. ## Uuid as ids All ids used by Timekit are uuid. Uuid looks like this: **de305d54-75b4-431b-adb2-eb6b9e546014** Read more about uuids [here](https://en.wikipedia.org/wiki/Universally_unique_identifier)
[block:callout] { "type": "success", "title": "Welcome to Timekit", "body": "We'd love to hear what you're building! Throw us an email at [yourfriends@timekit.io](mailto:yourfriends@timekit.io) or chat with us (Intercom, lower right corner) and let's help you get off the ground together." } [/block] [block:callout] { "type": "info", "title": "Getting started guides", "body": "Make your first API calls and learn by example with our quickstart guides:\n1) [Setup resources & calendars](doc:guide-connect-and-setup-google-user)\n2) [Availability search & find time](doc:guide-find-time-book-appointment)\n3) [Creating & managing bookings](doc:guide-bookings)" } [/block] The Timekit API is organized around [REST](http://en.wikipedia.org/wiki/Representational_State_Transfer). Our API is designed to follow common HTTP conventions including response codes to indicate both errors and successful requests. Standard HTTP verbs (GET, POST, PUT, DELETE) are used for all methods, no exceptions. [JSON](http://www.json.org/) will be returned in all responses from the API, including error messages. ## Root endpoint, versions and protocol All API calls should be made to `https://api.timekit.io/v2` (note the explicit versioning). The current public version of the API is **version 2** and is the only publicly supported version (calls to v1 will result in 404 Not Found). HTTP over TLS 1.2 is enforced for all calls, so non-secure calls will result in a 301 Moved Permanently pointing to the https URI. ## CORS Our API is intended to be consumed both by browser clients (e.g. [SPA](http://en.wikipedia.org/wiki/Single-page_application)s) and servers and supports [cross-origin resource sharing](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing). As of right now, JSONP is not supported, but we'd love to hear from you if it's of interest. ## Application context We provide a simple mechanism for tracking and bucketing app developers usage of the API by "tagging" all requests with an app ID. Read more about the application context [here](doc:application-context) For demo purposes in the documentation, this value is always set to "back-to-the-future", you cannot use this test-application yourself. ## Uuid as ids All ids used by Timekit are uuid. Uuid looks like this: **de305d54-75b4-431b-adb2-eb6b9e546014** Read more about uuids [here](https://en.wikipedia.org/wiki/Universally_unique_identifier)
{"_id":"55102c758579861900a866a2","order":1,"parentDoc":null,"updates":[],"body":"All authentication is user-based and working with the API is based on the current authenticated user's privileges. We regard users and resources as the same entity, this might be a bit confusing, but regarding authentication, we will stick to the \"user\" term because it makes the most sense when talking about authentication. Each user only has access to their own calendars, events, meetings etc. with one exception ([POST /findtime](doc:findtime) allows you to search across multiple users/resources)\n\n## Basic Authentication\n\nFor simple email/password authentication, we use Basic Authentication over HTTPS. Auth is stateless and is sent as Base64 encoded header with each HTTP request.\n\nEach user has a password which is used to retrieve an **API token** that should go with every subsequent request. The API token is returned when you create the user using [POST /resources](doc:resources) - *remember to save the token on your end!*\n\nMaking API requests is a matter of supplying the email and API token as authentication headers:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl \\\\\\n  -H 'Timekit-App: back-to-the-future' \\\\\\n  -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n  https://api.timekit.io/v2/calendars\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Timekit-App header\",\n  \"body\": \"All requests you make to Timekit will need to include a `Timekit-App` with your registered app slug. Read more about this [here](doc:application-context)\"\n}\n[/block]\n\n## Google Authentication\n\nIn addition to e-mail/password auth, we also support login and sync with Google accounts. The authentication flow is quite different.\n\n**Signup and login**\nUsers can signup AND login with their Google account using the [[GET] /accounts/google/signup](doc:accountsgooglesignup) endpoint. It will return a Google URL you should redirect the user to. When the user submits their credentials, our API will be pinged with the provided information. If the e-mail isn’t known to Timekit, a new user will be created. If the email is known, the user will be authenticated to Timekit. After a successful signup/login, we’ll redirect the user to your supplied callback with login info (email, api_token etc.) as GET parameters so you can perform authenticated calls after that. Make sure to save the API token for subsequent requests.\n\n**Calendar sync**\nThe first time a user is created, you should have them pick the calendars they want to sync (or do it for them). This happens on a per calendar basis, through the [[PUT] /calendars/:id](doc:calendarsid-2) endpoint.\n\nOnce calendars have been toggled, you can initiate a sync with the [[GET] /accounts/sync](doc:accountssync) endpoint.\n\n\n## Client-side Authentication\n\nIf you're building a frontend application and want to use Timekit API as a backend that users authenticate against directly, you can make them login using email and password to retrieve your a user's API token:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X POST \\\\\\n   -H 'Timekit-App: back-to-the-future' \\\\\\n   -d '{\\n         \\\"email\\\": \\\"doc.brown@timekit.io\\\",\\n         \\\"password\\\": \\\"FluxCapacitator\\\"\\n       }' \\\\\\n   https://api.timekit.io/v2/auth\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nWhich will return:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"data\\\": {\\n        \\\"activated\\\": true,\\n        \\\"email\\\": \\\"doc.brown@timekit.io\\\",\\n        \\\"first_name\\\": \\\"Dr. Emmett\\\",\\n        \\\"img\\\": \\\"http://www.gravatar.com/avatar/7a613e5348d63476276935025\\\",\\n        \\\"last_name\\\": \\\"Brown\\\",\\n        \\\"last_sync\\\": null,\\n        \\\"name\\\": \\\"Dr. Emmett Brown\\\",\\n        \\\"timezone\\\": \\\"America/Los_Angeles\\\",\\n        \\\"token_generated_at\\\": null,\\n        \\\"api_token\\\": \\\"nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW\\\",\\n    }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nThe `email` and `api_token` in the response is what you'll use for subsequent requests to the API as described above.","hidden":false,"next":{"description":"","pages":[]},"link_external":false,"sync_unique":"","type":"basic","version":"550bfb5522ccb01700a79469","createdAt":"2015-03-23T15:08:37.416Z","excerpt":"","githubsync":"","isReference":true,"api":{"settings":"","url":"","auth":"required","params":[],"results":{"codes":[{"name":"","status":200,"language":"json","code":"{}"},{"language":"json","code":"{}","name":"","status":400}]}},"link_url":"","project":"550ada512188a71900453199","user":"550bf7b2eb24860d00e6a33b","__v":26,"category":"550bfb5622ccb01700a7946a","slug":"authentication","title":"Authentication","childrenPages":[]}

Authentication


All authentication is user-based and working with the API is based on the current authenticated user's privileges. We regard users and resources as the same entity, this might be a bit confusing, but regarding authentication, we will stick to the "user" term because it makes the most sense when talking about authentication. Each user only has access to their own calendars, events, meetings etc. with one exception ([POST /findtime](doc:findtime) allows you to search across multiple users/resources) ## Basic Authentication For simple email/password authentication, we use Basic Authentication over HTTPS. Auth is stateless and is sent as Base64 encoded header with each HTTP request. Each user has a password which is used to retrieve an **API token** that should go with every subsequent request. The API token is returned when you create the user using [POST /resources](doc:resources) - *remember to save the token on your end!* Making API requests is a matter of supplying the email and API token as authentication headers: [block:code] { "codes": [ { "code": "curl \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/calendars", "language": "curl" } ] } [/block] [block:callout] { "type": "info", "title": "Timekit-App header", "body": "All requests you make to Timekit will need to include a `Timekit-App` with your registered app slug. Read more about this [here](doc:application-context)" } [/block] ## Google Authentication In addition to e-mail/password auth, we also support login and sync with Google accounts. The authentication flow is quite different. **Signup and login** Users can signup AND login with their Google account using the [[GET] /accounts/google/signup](doc:accountsgooglesignup) endpoint. It will return a Google URL you should redirect the user to. When the user submits their credentials, our API will be pinged with the provided information. If the e-mail isn’t known to Timekit, a new user will be created. If the email is known, the user will be authenticated to Timekit. After a successful signup/login, we’ll redirect the user to your supplied callback with login info (email, api_token etc.) as GET parameters so you can perform authenticated calls after that. Make sure to save the API token for subsequent requests. **Calendar sync** The first time a user is created, you should have them pick the calendars they want to sync (or do it for them). This happens on a per calendar basis, through the [[PUT] /calendars/:id](doc:calendarsid-2) endpoint. Once calendars have been toggled, you can initiate a sync with the [[GET] /accounts/sync](doc:accountssync) endpoint. ## Client-side Authentication If you're building a frontend application and want to use Timekit API as a backend that users authenticate against directly, you can make them login using email and password to retrieve your a user's API token: [block:code] { "codes": [ { "code": "curl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -d '{\n \"email\": \"doc.brown@timekit.io\",\n \"password\": \"FluxCapacitator\"\n }' \\\n https://api.timekit.io/v2/auth", "language": "curl" } ] } [/block] Which will return: [block:code] { "codes": [ { "code": "{\n \"data\": {\n \"activated\": true,\n \"email\": \"doc.brown@timekit.io\",\n \"first_name\": \"Dr. Emmett\",\n \"img\": \"http://www.gravatar.com/avatar/7a613e5348d63476276935025\",\n \"last_name\": \"Brown\",\n \"last_sync\": null,\n \"name\": \"Dr. Emmett Brown\",\n \"timezone\": \"America/Los_Angeles\",\n \"token_generated_at\": null,\n \"api_token\": \"nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW\",\n }\n}", "language": "json" } ] } [/block] The `email` and `api_token` in the response is what you'll use for subsequent requests to the API as described above.
All authentication is user-based and working with the API is based on the current authenticated user's privileges. We regard users and resources as the same entity, this might be a bit confusing, but regarding authentication, we will stick to the "user" term because it makes the most sense when talking about authentication. Each user only has access to their own calendars, events, meetings etc. with one exception ([POST /findtime](doc:findtime) allows you to search across multiple users/resources) ## Basic Authentication For simple email/password authentication, we use Basic Authentication over HTTPS. Auth is stateless and is sent as Base64 encoded header with each HTTP request. Each user has a password which is used to retrieve an **API token** that should go with every subsequent request. The API token is returned when you create the user using [POST /resources](doc:resources) - *remember to save the token on your end!* Making API requests is a matter of supplying the email and API token as authentication headers: [block:code] { "codes": [ { "code": "curl \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/calendars", "language": "curl" } ] } [/block] [block:callout] { "type": "info", "title": "Timekit-App header", "body": "All requests you make to Timekit will need to include a `Timekit-App` with your registered app slug. Read more about this [here](doc:application-context)" } [/block] ## Google Authentication In addition to e-mail/password auth, we also support login and sync with Google accounts. The authentication flow is quite different. **Signup and login** Users can signup AND login with their Google account using the [[GET] /accounts/google/signup](doc:accountsgooglesignup) endpoint. It will return a Google URL you should redirect the user to. When the user submits their credentials, our API will be pinged with the provided information. If the e-mail isn’t known to Timekit, a new user will be created. If the email is known, the user will be authenticated to Timekit. After a successful signup/login, we’ll redirect the user to your supplied callback with login info (email, api_token etc.) as GET parameters so you can perform authenticated calls after that. Make sure to save the API token for subsequent requests. **Calendar sync** The first time a user is created, you should have them pick the calendars they want to sync (or do it for them). This happens on a per calendar basis, through the [[PUT] /calendars/:id](doc:calendarsid-2) endpoint. Once calendars have been toggled, you can initiate a sync with the [[GET] /accounts/sync](doc:accountssync) endpoint. ## Client-side Authentication If you're building a frontend application and want to use Timekit API as a backend that users authenticate against directly, you can make them login using email and password to retrieve your a user's API token: [block:code] { "codes": [ { "code": "curl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -d '{\n \"email\": \"doc.brown@timekit.io\",\n \"password\": \"FluxCapacitator\"\n }' \\\n https://api.timekit.io/v2/auth", "language": "curl" } ] } [/block] Which will return: [block:code] { "codes": [ { "code": "{\n \"data\": {\n \"activated\": true,\n \"email\": \"doc.brown@timekit.io\",\n \"first_name\": \"Dr. Emmett\",\n \"img\": \"http://www.gravatar.com/avatar/7a613e5348d63476276935025\",\n \"last_name\": \"Brown\",\n \"last_sync\": null,\n \"name\": \"Dr. Emmett Brown\",\n \"timezone\": \"America/Los_Angeles\",\n \"token_generated_at\": null,\n \"api_token\": \"nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW\",\n }\n}", "language": "json" } ] } [/block] The `email` and `api_token` in the response is what you'll use for subsequent requests to the API as described above.
{"_id":"55cbd35f9d3dc20d009494b6","link_external":false,"project":"550ada512188a71900453199","sync_unique":"","__v":5,"body":"We provide a simple mechanism for tracking and bucketing app developers usage of the API by \"tagging\" all requests with an app ID. Whenever you make an API call, the app ID should included.\n\n## Timekit-App setting\nAdd the app context with a custom HTTP header called \"Timekit-App\", like so:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X GET \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     https://api.timekit.io/v2/resources/me\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nIn cases where its not possible to set a HTTP header (e.g. in webhooks on third-party services), you can provide a query param named \"Timekit-App\" in the URL instead:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X GET \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     https://api.timekit.io/v2/resources/me?Timekit-App=back-to-the-future\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\n## Register new app\nFor demo purposes in the documentation, the app slug in examples are always set to \"back-to-the-future\". You cannot use this yourself and must replace it with your own app slug.\n\nIf you start making requests outside the documentation (e.g. in production apps), you need to register your app: [Create an admin user and register your app](http://timekit.io/get-started) form\n\nThe \"app slug\" is the value you should use in your requests.\n\nWe'd love to hear from you on what you're planning to build, so don't hesitate to contact us!","category":"550bfb5622ccb01700a7946a","createdAt":"2015-08-12T23:14:39.450Z","excerpt":"","link_url":"","order":2,"updates":[],"version":"550bfb5522ccb01700a79469","api":{"url":"","auth":"required","params":[],"results":{"codes":[{"language":"json","code":"{}","name":"","status":200},{"status":400,"language":"json","code":"{}","name":""}]},"settings":""},"hidden":false,"isReference":true,"next":{"description":"","pages":[]},"title":"App context","githubsync":"","parentDoc":null,"slug":"application-context","type":"basic","user":"550bf7b2eb24860d00e6a33b","childrenPages":[]}

App context


We provide a simple mechanism for tracking and bucketing app developers usage of the API by "tagging" all requests with an app ID. Whenever you make an API call, the app ID should included. ## Timekit-App setting Add the app context with a custom HTTP header called "Timekit-App", like so: [block:code] { "codes": [ { "code": "curl -X GET \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/resources/me", "language": "curl" } ] } [/block] In cases where its not possible to set a HTTP header (e.g. in webhooks on third-party services), you can provide a query param named "Timekit-App" in the URL instead: [block:code] { "codes": [ { "code": "curl -X GET \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/resources/me?Timekit-App=back-to-the-future", "language": "curl" } ] } [/block] ## Register new app For demo purposes in the documentation, the app slug in examples are always set to "back-to-the-future". You cannot use this yourself and must replace it with your own app slug. If you start making requests outside the documentation (e.g. in production apps), you need to register your app: [Create an admin user and register your app](http://timekit.io/get-started) form The "app slug" is the value you should use in your requests. We'd love to hear from you on what you're planning to build, so don't hesitate to contact us!
We provide a simple mechanism for tracking and bucketing app developers usage of the API by "tagging" all requests with an app ID. Whenever you make an API call, the app ID should included. ## Timekit-App setting Add the app context with a custom HTTP header called "Timekit-App", like so: [block:code] { "codes": [ { "code": "curl -X GET \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/resources/me", "language": "curl" } ] } [/block] In cases where its not possible to set a HTTP header (e.g. in webhooks on third-party services), you can provide a query param named "Timekit-App" in the URL instead: [block:code] { "codes": [ { "code": "curl -X GET \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/resources/me?Timekit-App=back-to-the-future", "language": "curl" } ] } [/block] ## Register new app For demo purposes in the documentation, the app slug in examples are always set to "back-to-the-future". You cannot use this yourself and must replace it with your own app slug. If you start making requests outside the documentation (e.g. in production apps), you need to register your app: [Create an admin user and register your app](http://timekit.io/get-started) form The "app slug" is the value you should use in your requests. We'd love to hear from you on what you're planning to build, so don't hesitate to contact us!
{"_id":"55393bba8d56860d00c1ce91","slug":"types--formatting","sync_unique":"","title":"Types & formatting","hidden":false,"next":{"description":"","pages":[]},"link_external":false,"order":3,"api":{"url":"","auth":"required","params":[],"results":{"codes":[{"status":200,"language":"json","code":"{}","name":""},{"language":"json","code":"{}","name":"","status":400}]},"settings":""},"category":"550bfb5622ccb01700a7946a","excerpt":"","githubsync":"","isReference":true,"project":"550ada512188a71900453199","updates":[],"user":"550bf7b2eb24860d00e6a33b","__v":22,"body":"## Date formats\n\nOur API is build around the idea that the client should control the response as much as possible. So when you make requests, you can decide the date format that will be returned, like so: \n\nInput and output date formats are set in the header or in a query params.\n\nTo choose output format use: Timekit-OutputTimestampFormat\nTo choose input format use: Timekit-InputTimestampFormat\n\nDefault format: ISO_8601 eg. **2016-05-26T15:30:00+00:00** \n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"If you're passing a timestamp as a GET parameter in a URL, the **+** sign needs to be URL safe encoded. Replace it with: %2B\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Output timestamps date in a custom format\",\n  \"body\": \"Add a header: **'Timekit-OutputTimestampFormat: Y-m-d h:ia' **or as a query param: **?Timekit-OutputTimestampFormat=Y-m-d h:ia**\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X POST \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -H 'Timekit-OutputTimestampFormat: Y-m-d h:ia' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n           \\\"emails\\\": [\\n             \\\"doc.brown@timekit.io\\\",\\n             \\\"marty.mcfly@timekit.io\\\"\\n           ],\\n           \\\"future\\\": \\\"2 days\\\",\\n           \\\"length\\\": \\\"30 minutes\\\",\\n           \\\"format\\\": \\\"Y-m-d h:ia\\\"\\n         }' \\\\\\n     https://api.timekit.io/v2/findtime\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nThis will return:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"data\\\": [\\n        {\\n            \\\"end\\\": \\\"2015-04-24 09:30am\\\",\\n            \\\"start\\\": \\\"2015-04-24 09:00am\\\"\\n        },\\n        {\\n            \\\"end\\\": \\\"2015-04-24 12:15pm\\\",\\n            \\\"start\\\": \\\"2015-04-24 11:45am\\\"\\n        },\\n        {\\n            \\\"end\\\": \\\"2015-04-24 06:15pm\\\",\\n            \\\"start\\\": \\\"2015-04-24 05:45pm\\\"\\n        },\\n        {\\n            \\\"end\\\": \\\"2015-04-24 08:15pm\\\",\\n            \\\"start\\\": \\\"2015-04-24 07:45pm\\\"\\n        },\\n        {\\n            \\\"end\\\": \\\"2015-04-25 08:00am\\\",\\n            \\\"start\\\": \\\"2015-04-25 07:30am\\\"\\n        }\\n    ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nThe data format is defined in the *format* params, where the following options is available:\n[block:parameters]\n{\n  \"data\": {\n    \"0-0\": \"d\",\n    \"0-1\": \"Day of the month, 2 digits with leading zeros\",\n    \"0-2\": \"01 to 31\",\n    \"h-0\": \"Format\",\n    \"h-1\": \"Description\",\n    \"h-2\": \"Example\",\n    \"1-0\": \"l\",\n    \"1-1\": \"(lowercase 'L') A full textual representation of the day of the week\",\n    \"1-2\": \"Sunday through Saturday\",\n    \"2-0\": \"m\",\n    \"2-1\": \"Numeric representation of a month, with leading zeros\",\n    \"2-2\": \"01 through 12\",\n    \"3-0\": \"Y\",\n    \"3-1\": \"A full numeric representation of a year, 4 digits\",\n    \"3-2\": \"Examples: 1999 or 2003\",\n    \"4-0\": \"a\",\n    \"4-1\": \"Lowercase Ante meridiem and Post meridiem\",\n    \"4-2\": \"am or pm\",\n    \"5-0\": \"h\",\n    \"5-1\": \"12-hour format of an hour with leading zeros\",\n    \"5-2\": \"01 through 12\",\n    \"6-0\": \"H\",\n    \"6-1\": \"24-hour format of an hour with leading zeros\",\n    \"6-2\": \"00 through 23\",\n    \"7-0\": \"i\",\n    \"7-1\": \"Minutes with leading zeros\",\n    \"7-2\": \"00 through 59\",\n    \"8-0\": \"s\",\n    \"8-1\": \"Seconds, with leading zeros\",\n    \"8-2\": \"00 through 59\",\n    \"9-0\": \"Y-m-d\\\\TH:i:sO\",\n    \"9-1\": \"ISO 8601 date\",\n    \"9-2\": \"2004-02-26T15:19:21+00:00\",\n    \"10-0\": \"U\",\n    \"10-1\": \"Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)\",\n    \"10-2\": \"1429866000\"\n  },\n  \"cols\": 3,\n  \"rows\": 11\n}\n[/block]\n## Timezones\n\nEvery timestamp on Timekit is saved in UTC by default.\nTimezones are written and formatted using the Country/City convention, like `America/Los_Angeles`\n\nEach resource has a timezone and it can be retrieved by calling the */resources/me* endpoint:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"data\\\": {\\n        \\\"activated\\\": true,\\n        \\\"email\\\": \\\"doc.brown@timekit.io\\\",\\n        \\\"first_name\\\": \\\"Dr. Emmett\\\",\\n        \\\"img\\\": \\\"http://www.gravatar.com/avatar/7a613e5348d63476276935025\\\",\\n        \\\"last_name\\\": \\\"Brown\\\",\\n        \\\"last_sync\\\": null,\\n        \\\"name\\\": \\\"Dr. Emmett Brown\\\",\\n        \\\"timezone\\\": \\\"America/Los_Angeles\\\",\\n        \\\"token\\\": \\\"nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW\\\",\\n        \\\"token_generated_at\\\": null\\n    }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]","createdAt":"2015-04-23T18:36:42.749Z","version":"550bfb5522ccb01700a79469","link_url":"","parentDoc":null,"type":"basic","childrenPages":[]}

Types & formatting


## Date formats Our API is build around the idea that the client should control the response as much as possible. So when you make requests, you can decide the date format that will be returned, like so: Input and output date formats are set in the header or in a query params. To choose output format use: Timekit-OutputTimestampFormat To choose input format use: Timekit-InputTimestampFormat Default format: ISO_8601 eg. **2016-05-26T15:30:00+00:00** [block:callout] { "type": "warning", "body": "If you're passing a timestamp as a GET parameter in a URL, the **+** sign needs to be URL safe encoded. Replace it with: %2B" } [/block] [block:callout] { "type": "success", "title": "Output timestamps date in a custom format", "body": "Add a header: **'Timekit-OutputTimestampFormat: Y-m-d h:ia' **or as a query param: **?Timekit-OutputTimestampFormat=Y-m-d h:ia**" } [/block] [block:code] { "codes": [ { "code": "curl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -H 'Timekit-OutputTimestampFormat: Y-m-d h:ia' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"emails\": [\n \"doc.brown@timekit.io\",\n \"marty.mcfly@timekit.io\"\n ],\n \"future\": \"2 days\",\n \"length\": \"30 minutes\",\n \"format\": \"Y-m-d h:ia\"\n }' \\\n https://api.timekit.io/v2/findtime", "language": "curl" } ] } [/block] This will return: [block:code] { "codes": [ { "code": "{\n \"data\": [\n {\n \"end\": \"2015-04-24 09:30am\",\n \"start\": \"2015-04-24 09:00am\"\n },\n {\n \"end\": \"2015-04-24 12:15pm\",\n \"start\": \"2015-04-24 11:45am\"\n },\n {\n \"end\": \"2015-04-24 06:15pm\",\n \"start\": \"2015-04-24 05:45pm\"\n },\n {\n \"end\": \"2015-04-24 08:15pm\",\n \"start\": \"2015-04-24 07:45pm\"\n },\n {\n \"end\": \"2015-04-25 08:00am\",\n \"start\": \"2015-04-25 07:30am\"\n }\n ]\n}", "language": "json" } ] } [/block] The data format is defined in the *format* params, where the following options is available: [block:parameters] { "data": { "0-0": "d", "0-1": "Day of the month, 2 digits with leading zeros", "0-2": "01 to 31", "h-0": "Format", "h-1": "Description", "h-2": "Example", "1-0": "l", "1-1": "(lowercase 'L') A full textual representation of the day of the week", "1-2": "Sunday through Saturday", "2-0": "m", "2-1": "Numeric representation of a month, with leading zeros", "2-2": "01 through 12", "3-0": "Y", "3-1": "A full numeric representation of a year, 4 digits", "3-2": "Examples: 1999 or 2003", "4-0": "a", "4-1": "Lowercase Ante meridiem and Post meridiem", "4-2": "am or pm", "5-0": "h", "5-1": "12-hour format of an hour with leading zeros", "5-2": "01 through 12", "6-0": "H", "6-1": "24-hour format of an hour with leading zeros", "6-2": "00 through 23", "7-0": "i", "7-1": "Minutes with leading zeros", "7-2": "00 through 59", "8-0": "s", "8-1": "Seconds, with leading zeros", "8-2": "00 through 59", "9-0": "Y-m-d\\TH:i:sO", "9-1": "ISO 8601 date", "9-2": "2004-02-26T15:19:21+00:00", "10-0": "U", "10-1": "Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)", "10-2": "1429866000" }, "cols": 3, "rows": 11 } [/block] ## Timezones Every timestamp on Timekit is saved in UTC by default. Timezones are written and formatted using the Country/City convention, like `America/Los_Angeles` Each resource has a timezone and it can be retrieved by calling the */resources/me* endpoint: [block:code] { "codes": [ { "code": "{\n \"data\": {\n \"activated\": true,\n \"email\": \"doc.brown@timekit.io\",\n \"first_name\": \"Dr. Emmett\",\n \"img\": \"http://www.gravatar.com/avatar/7a613e5348d63476276935025\",\n \"last_name\": \"Brown\",\n \"last_sync\": null,\n \"name\": \"Dr. Emmett Brown\",\n \"timezone\": \"America/Los_Angeles\",\n \"token\": \"nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW\",\n \"token_generated_at\": null\n }\n}", "language": "json" } ] } [/block]
## Date formats Our API is build around the idea that the client should control the response as much as possible. So when you make requests, you can decide the date format that will be returned, like so: Input and output date formats are set in the header or in a query params. To choose output format use: Timekit-OutputTimestampFormat To choose input format use: Timekit-InputTimestampFormat Default format: ISO_8601 eg. **2016-05-26T15:30:00+00:00** [block:callout] { "type": "warning", "body": "If you're passing a timestamp as a GET parameter in a URL, the **+** sign needs to be URL safe encoded. Replace it with: %2B" } [/block] [block:callout] { "type": "success", "title": "Output timestamps date in a custom format", "body": "Add a header: **'Timekit-OutputTimestampFormat: Y-m-d h:ia' **or as a query param: **?Timekit-OutputTimestampFormat=Y-m-d h:ia**" } [/block] [block:code] { "codes": [ { "code": "curl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -H 'Timekit-OutputTimestampFormat: Y-m-d h:ia' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"emails\": [\n \"doc.brown@timekit.io\",\n \"marty.mcfly@timekit.io\"\n ],\n \"future\": \"2 days\",\n \"length\": \"30 minutes\",\n \"format\": \"Y-m-d h:ia\"\n }' \\\n https://api.timekit.io/v2/findtime", "language": "curl" } ] } [/block] This will return: [block:code] { "codes": [ { "code": "{\n \"data\": [\n {\n \"end\": \"2015-04-24 09:30am\",\n \"start\": \"2015-04-24 09:00am\"\n },\n {\n \"end\": \"2015-04-24 12:15pm\",\n \"start\": \"2015-04-24 11:45am\"\n },\n {\n \"end\": \"2015-04-24 06:15pm\",\n \"start\": \"2015-04-24 05:45pm\"\n },\n {\n \"end\": \"2015-04-24 08:15pm\",\n \"start\": \"2015-04-24 07:45pm\"\n },\n {\n \"end\": \"2015-04-25 08:00am\",\n \"start\": \"2015-04-25 07:30am\"\n }\n ]\n}", "language": "json" } ] } [/block] The data format is defined in the *format* params, where the following options is available: [block:parameters] { "data": { "0-0": "d", "0-1": "Day of the month, 2 digits with leading zeros", "0-2": "01 to 31", "h-0": "Format", "h-1": "Description", "h-2": "Example", "1-0": "l", "1-1": "(lowercase 'L') A full textual representation of the day of the week", "1-2": "Sunday through Saturday", "2-0": "m", "2-1": "Numeric representation of a month, with leading zeros", "2-2": "01 through 12", "3-0": "Y", "3-1": "A full numeric representation of a year, 4 digits", "3-2": "Examples: 1999 or 2003", "4-0": "a", "4-1": "Lowercase Ante meridiem and Post meridiem", "4-2": "am or pm", "5-0": "h", "5-1": "12-hour format of an hour with leading zeros", "5-2": "01 through 12", "6-0": "H", "6-1": "24-hour format of an hour with leading zeros", "6-2": "00 through 23", "7-0": "i", "7-1": "Minutes with leading zeros", "7-2": "00 through 59", "8-0": "s", "8-1": "Seconds, with leading zeros", "8-2": "00 through 59", "9-0": "Y-m-d\\TH:i:sO", "9-1": "ISO 8601 date", "9-2": "2004-02-26T15:19:21+00:00", "10-0": "U", "10-1": "Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)", "10-2": "1429866000" }, "cols": 3, "rows": 11 } [/block] ## Timezones Every timestamp on Timekit is saved in UTC by default. Timezones are written and formatted using the Country/City convention, like `America/Los_Angeles` Each resource has a timezone and it can be retrieved by calling the */resources/me* endpoint: [block:code] { "codes": [ { "code": "{\n \"data\": {\n \"activated\": true,\n \"email\": \"doc.brown@timekit.io\",\n \"first_name\": \"Dr. Emmett\",\n \"img\": \"http://www.gravatar.com/avatar/7a613e5348d63476276935025\",\n \"last_name\": \"Brown\",\n \"last_sync\": null,\n \"name\": \"Dr. Emmett Brown\",\n \"timezone\": \"America/Los_Angeles\",\n \"token\": \"nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW\",\n \"token_generated_at\": null\n }\n}", "language": "json" } ] } [/block]
{"_id":"5538724cf426ca0d003ae392","githubsync":"","hidden":false,"isReference":true,"link_url":"","parentDoc":null,"title":"Dynamic includes","type":"basic","createdAt":"2015-04-23T04:17:16.044Z","category":"550bfb5622ccb01700a7946a","excerpt":"","next":{"description":"","pages":[]},"project":"550ada512188a71900453199","__v":16,"slug":"dynamic-includes","user":"550bf7b2eb24860d00e6a33b","link_external":false,"api":{"results":{"codes":[{"status":200,"language":"json","code":"{}","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"","auth":"required","params":[]},"body":"On most resources, you can dynamically include related objects (aka. expand objects). E.g. for a resource you can include the resource' calendars in the response by adding *?include=calendars* to the URL. What is available where will be listed under each resource. You may also supply multiple objects that you want to fetch by separating them with commas, e.g. *?include=calendars,accounts*\n\nSo running this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl \\\\\\n\\t-H 'Timekit-App: back-to-the-future' \\\\\\n  -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n  https://api.timekit.io/v2/resources/me?include=calendars \",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nWill return:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"data\\\": {\\n        \\\"activated\\\": true,\\n        \\\"calendars\\\": [\\n            {\\n                \\\"backgroundcolor\\\": \\\"#FFFFFF\\\",\\n                \\\"description\\\": \\\"Doc. Browns calendar\\\",\\n                \\\"foregroundcolor\\\": \\\"#000000\\\",\\n                \\\"name\\\": \\\"Doc\\\",\\n                \\\"system\\\": false\\n            }\\n        ],\\n        \\\"email\\\": \\\"doc.brown@timekit.io\\\",\\n        \\\"first_name\\\": \\\"Dr. Emmett\\\",\\n        \\\"img\\\": \\\"http://www.gravatar.com/avatar/7a613e5348d63476276935025\\\",\\n        \\\"last_name\\\": \\\"Brown\\\",\\n        \\\"last_sync\\\": null,\\n        \\\"name\\\": \\\"Dr. Emmett Brown\\\",\\n        \\\"timezone\\\": \\\"America/Los_Angeles\\\",\\n        \\\"token\\\": \\\"UZpl3v3PTP1PRwqIrU0DSVpbJkNKl5gN\\\"\\n    }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nYou can include data in nested layers, so if you include calendars then you can include events also (since events are nested under calendars). You do that by using the dot annotation, so *?include=calendars.events*, will return you calendars including their events.\n\nSo running this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl \\\\\\n\\t-H 'Timekit-App: back-to-the-future' \\\\\\n  -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n  https://api.timekit.io/v2/resources/me?include=calendars.events \",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nWill return:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"data\\\": {\\n        \\\"activated\\\": true,\\n        \\\"calendars\\\": [\\n            {\\n                \\\"backgroundcolor\\\": \\\"#FFFFFF\\\",\\n                \\\"description\\\": \\\"Doc. Browns calendar\\\",\\n                \\\"events\\\": [\\n                    {\\n                      \\\"id\\\": \\\"892d7425-ea2d-4d7d-a74e-e69fad7813cc\\\",\\n                      \\\"what\\\": \\\"Update\\\",\\n                      \\\"where\\\": \\\"Skype\\\",\\n                      \\\"rsvp\\\": \\\"needsAction\\\",\\n                      \\\"allDay\\\": false,\\n                      \\\"start\\\": \\\"2014-10-14T14:30:00+00:00\\\",\\n                      \\\"end\\\": \\\"2014-10-14T15:30:00+00:00\\\",\\n                      \\\"description\\\": \\\"Update about the FluxCapacitator\\\"\\n                    },\\n                    {\\n                      \\\"id\\\": \\\"4b08a047-3133-41f1-83e1-27cb933d8dbb\\\",\\n                      \\\"what\\\": \\\"Strategy Meeting\\\",\\n                      \\\"where\\\": \\\"1355 Market st, San Francisco, CA\\\",\\n                      \\\"rsvp\\\": \\\"accepted\\\",\\n                      \\\"allDay\\\": false,\\n                      \\\"start\\\": \\\"2014-10-14T10:00:00+00:00\\\",\\n                      \\\"end\\\": \\\"2014-10-14T12:00:00+00:00\\\",\\n                      \\\"description\\\": \\\"How to make a timemachine\\\"\\n                    },\\n                ],\\n                \\\"foregroundcolor\\\": \\\"#000000\\\",\\n                \\\"name\\\": \\\"Doc\\\",\\n                \\\"system\\\": false\\n            }\\n        ],\\n        \\\"email\\\": \\\"doc.brown@timekit.io\\\",\\n        \\\"first_name\\\": \\\"Dr. Emmett\\\",\\n        \\\"img\\\": \\\"http://www.gravatar.com/avatar/7a613e5348d63476276935025\\\",\\n        \\\"last_name\\\": \\\"Brown\\\",\\n        \\\"last_sync\\\": null,\\n        \\\"name\\\": \\\"Dr. Emmett Brown\\\",\\n        \\\"timezone\\\": \\\"America/Los_Angeles\\\",\\n        \\\"token\\\": \\\"UZpl3v3PTP1PRwqIrU0DSVpbJkNKl5gN\\\"\\n    }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]","order":4,"sync_unique":"","updates":[],"version":"550bfb5522ccb01700a79469","childrenPages":[]}

Dynamic includes


On most resources, you can dynamically include related objects (aka. expand objects). E.g. for a resource you can include the resource' calendars in the response by adding *?include=calendars* to the URL. What is available where will be listed under each resource. You may also supply multiple objects that you want to fetch by separating them with commas, e.g. *?include=calendars,accounts* So running this: [block:code] { "codes": [ { "code": "curl \\\n\t-H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/resources/me?include=calendars ", "language": "curl" } ] } [/block] Will return: [block:code] { "codes": [ { "code": "{\n \"data\": {\n \"activated\": true,\n \"calendars\": [\n {\n \"backgroundcolor\": \"#FFFFFF\",\n \"description\": \"Doc. Browns calendar\",\n \"foregroundcolor\": \"#000000\",\n \"name\": \"Doc\",\n \"system\": false\n }\n ],\n \"email\": \"doc.brown@timekit.io\",\n \"first_name\": \"Dr. Emmett\",\n \"img\": \"http://www.gravatar.com/avatar/7a613e5348d63476276935025\",\n \"last_name\": \"Brown\",\n \"last_sync\": null,\n \"name\": \"Dr. Emmett Brown\",\n \"timezone\": \"America/Los_Angeles\",\n \"token\": \"UZpl3v3PTP1PRwqIrU0DSVpbJkNKl5gN\"\n }\n}", "language": "json" } ] } [/block] You can include data in nested layers, so if you include calendars then you can include events also (since events are nested under calendars). You do that by using the dot annotation, so *?include=calendars.events*, will return you calendars including their events. So running this: [block:code] { "codes": [ { "code": "curl \\\n\t-H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/resources/me?include=calendars.events ", "language": "curl" } ] } [/block] Will return: [block:code] { "codes": [ { "code": "{\n \"data\": {\n \"activated\": true,\n \"calendars\": [\n {\n \"backgroundcolor\": \"#FFFFFF\",\n \"description\": \"Doc. Browns calendar\",\n \"events\": [\n {\n \"id\": \"892d7425-ea2d-4d7d-a74e-e69fad7813cc\",\n \"what\": \"Update\",\n \"where\": \"Skype\",\n \"rsvp\": \"needsAction\",\n \"allDay\": false,\n \"start\": \"2014-10-14T14:30:00+00:00\",\n \"end\": \"2014-10-14T15:30:00+00:00\",\n \"description\": \"Update about the FluxCapacitator\"\n },\n {\n \"id\": \"4b08a047-3133-41f1-83e1-27cb933d8dbb\",\n \"what\": \"Strategy Meeting\",\n \"where\": \"1355 Market st, San Francisco, CA\",\n \"rsvp\": \"accepted\",\n \"allDay\": false,\n \"start\": \"2014-10-14T10:00:00+00:00\",\n \"end\": \"2014-10-14T12:00:00+00:00\",\n \"description\": \"How to make a timemachine\"\n },\n ],\n \"foregroundcolor\": \"#000000\",\n \"name\": \"Doc\",\n \"system\": false\n }\n ],\n \"email\": \"doc.brown@timekit.io\",\n \"first_name\": \"Dr. Emmett\",\n \"img\": \"http://www.gravatar.com/avatar/7a613e5348d63476276935025\",\n \"last_name\": \"Brown\",\n \"last_sync\": null,\n \"name\": \"Dr. Emmett Brown\",\n \"timezone\": \"America/Los_Angeles\",\n \"token\": \"UZpl3v3PTP1PRwqIrU0DSVpbJkNKl5gN\"\n }\n}", "language": "json" } ] } [/block]
On most resources, you can dynamically include related objects (aka. expand objects). E.g. for a resource you can include the resource' calendars in the response by adding *?include=calendars* to the URL. What is available where will be listed under each resource. You may also supply multiple objects that you want to fetch by separating them with commas, e.g. *?include=calendars,accounts* So running this: [block:code] { "codes": [ { "code": "curl \\\n\t-H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/resources/me?include=calendars ", "language": "curl" } ] } [/block] Will return: [block:code] { "codes": [ { "code": "{\n \"data\": {\n \"activated\": true,\n \"calendars\": [\n {\n \"backgroundcolor\": \"#FFFFFF\",\n \"description\": \"Doc. Browns calendar\",\n \"foregroundcolor\": \"#000000\",\n \"name\": \"Doc\",\n \"system\": false\n }\n ],\n \"email\": \"doc.brown@timekit.io\",\n \"first_name\": \"Dr. Emmett\",\n \"img\": \"http://www.gravatar.com/avatar/7a613e5348d63476276935025\",\n \"last_name\": \"Brown\",\n \"last_sync\": null,\n \"name\": \"Dr. Emmett Brown\",\n \"timezone\": \"America/Los_Angeles\",\n \"token\": \"UZpl3v3PTP1PRwqIrU0DSVpbJkNKl5gN\"\n }\n}", "language": "json" } ] } [/block] You can include data in nested layers, so if you include calendars then you can include events also (since events are nested under calendars). You do that by using the dot annotation, so *?include=calendars.events*, will return you calendars including their events. So running this: [block:code] { "codes": [ { "code": "curl \\\n\t-H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/resources/me?include=calendars.events ", "language": "curl" } ] } [/block] Will return: [block:code] { "codes": [ { "code": "{\n \"data\": {\n \"activated\": true,\n \"calendars\": [\n {\n \"backgroundcolor\": \"#FFFFFF\",\n \"description\": \"Doc. Browns calendar\",\n \"events\": [\n {\n \"id\": \"892d7425-ea2d-4d7d-a74e-e69fad7813cc\",\n \"what\": \"Update\",\n \"where\": \"Skype\",\n \"rsvp\": \"needsAction\",\n \"allDay\": false,\n \"start\": \"2014-10-14T14:30:00+00:00\",\n \"end\": \"2014-10-14T15:30:00+00:00\",\n \"description\": \"Update about the FluxCapacitator\"\n },\n {\n \"id\": \"4b08a047-3133-41f1-83e1-27cb933d8dbb\",\n \"what\": \"Strategy Meeting\",\n \"where\": \"1355 Market st, San Francisco, CA\",\n \"rsvp\": \"accepted\",\n \"allDay\": false,\n \"start\": \"2014-10-14T10:00:00+00:00\",\n \"end\": \"2014-10-14T12:00:00+00:00\",\n \"description\": \"How to make a timemachine\"\n },\n ],\n \"foregroundcolor\": \"#000000\",\n \"name\": \"Doc\",\n \"system\": false\n }\n ],\n \"email\": \"doc.brown@timekit.io\",\n \"first_name\": \"Dr. Emmett\",\n \"img\": \"http://www.gravatar.com/avatar/7a613e5348d63476276935025\",\n \"last_name\": \"Brown\",\n \"last_sync\": null,\n \"name\": \"Dr. Emmett Brown\",\n \"timezone\": \"America/Los_Angeles\",\n \"token\": \"UZpl3v3PTP1PRwqIrU0DSVpbJkNKl5gN\"\n }\n}", "language": "json" } ] } [/block]
{"_id":"55102cd87f4a7a1900f5790e","order":5,"api":{"auth":"required","params":[],"results":{"codes":[{"name":"","status":200,"language":"json","code":"{}"},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":""},"body":"In general, responses follow common HTTP conventions as much as possible. \n[block:parameters]\n{\n  \"data\": {\n    \"0-0\": \"200\",\n    \"0-1\": \"OK\",\n    \"1-0\": \"201\",\n    \"1-1\": \"Created\",\n    \"1-2\": \"Returned when POSTing to create a new resource was successful\",\n    \"0-2\": \"Everything went okay\",\n    \"2-0\": \"400\",\n    \"2-1\": \"Bad Request\",\n    \"2-2\": \"The request was malformed (missing parameters throw 422)\",\n    \"3-0\": \"401\",\n    \"3-1\": \"Unauthorized\",\n    \"3-2\": \"Invalid credentials supplied\",\n    \"h-0\": \"Code\",\n    \"h-1\": \"Name\",\n    \"h-2\": \"Explanation\",\n    \"4-0\": \"422\",\n    \"4-1\": \"Unprocessable Entity\",\n    \"4-2\": \"A POST data JSON key or alike is malformed or missing\",\n    \"5-0\": \"500\",\n    \"5-1\": \"Internal Server Error\",\n    \"5-2\": \"If you encounter this, please get in touch - this should not happen\"\n  },\n  \"cols\": 3,\n  \"rows\": 6\n}\n[/block]\nIf non-existing fields are supplied, they are simply ignored and an error will not be returned (whitelisting approach).\n\n##Successful calls\n\nSuccessful requests that result in 200 response codes will have their data inside a key named \"data\":\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// 200 OK\\n{\\n  \\\"data\\\": \\\"Response data here\\\"\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n##Error messages \n\nWhenever an error occurs (e.g. validation), the API will attempt to write the error message inside a key named \"error\":\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// 400 Bad Request\\n{\\n\\t\\\"error\\\": {\\n\\t\\t\\\"message\\\": \\\"Error message here\\\",\\n    \\\"status_code\\\": 400\\n  }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIf more than one error occurs (e.g. multiple fields fail validation), the key will be named \"errors\" and the relevant messages will be contained in an array:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// 422 Bad Request\\n{\\n\\t\\\"errors\\\": {\\n\\t\\t\\\"first_name\\\": {\\n\\t\\t\\t\\\"The first name field is required.\\\"\\n    },\\n\\t\\t\\\"email\\\": {\\n\\t\\t\\t\\\"The email field is required.\\\"\\n    },\\n\\t\\t\\\"timezone\\\": {\\n\\t\\t\\t\\\"The timezone field is required.\\\"\\n    }\\n\\t}\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]","createdAt":"2015-03-23T15:10:16.111Z","githubsync":"","hidden":false,"isReference":true,"parentDoc":null,"title":"Responses & errors","type":"basic","excerpt":"","link_url":"","updates":[],"version":"550bfb5522ccb01700a79469","slug":"errors","sync_unique":"","user":"550bf7b2eb24860d00e6a33b","__v":11,"category":"550bfb5622ccb01700a7946a","link_external":false,"project":"550ada512188a71900453199","childrenPages":[]}

Responses & errors


In general, responses follow common HTTP conventions as much as possible. [block:parameters] { "data": { "0-0": "200", "0-1": "OK", "1-0": "201", "1-1": "Created", "1-2": "Returned when POSTing to create a new resource was successful", "0-2": "Everything went okay", "2-0": "400", "2-1": "Bad Request", "2-2": "The request was malformed (missing parameters throw 422)", "3-0": "401", "3-1": "Unauthorized", "3-2": "Invalid credentials supplied", "h-0": "Code", "h-1": "Name", "h-2": "Explanation", "4-0": "422", "4-1": "Unprocessable Entity", "4-2": "A POST data JSON key or alike is malformed or missing", "5-0": "500", "5-1": "Internal Server Error", "5-2": "If you encounter this, please get in touch - this should not happen" }, "cols": 3, "rows": 6 } [/block] If non-existing fields are supplied, they are simply ignored and an error will not be returned (whitelisting approach). ##Successful calls Successful requests that result in 200 response codes will have their data inside a key named "data": [block:code] { "codes": [ { "code": "// 200 OK\n{\n \"data\": \"Response data here\"\n}", "language": "json" } ] } [/block] ##Error messages Whenever an error occurs (e.g. validation), the API will attempt to write the error message inside a key named "error": [block:code] { "codes": [ { "code": "// 400 Bad Request\n{\n\t\"error\": {\n\t\t\"message\": \"Error message here\",\n \"status_code\": 400\n }\n}", "language": "json" } ] } [/block] If more than one error occurs (e.g. multiple fields fail validation), the key will be named "errors" and the relevant messages will be contained in an array: [block:code] { "codes": [ { "code": "// 422 Bad Request\n{\n\t\"errors\": {\n\t\t\"first_name\": {\n\t\t\t\"The first name field is required.\"\n },\n\t\t\"email\": {\n\t\t\t\"The email field is required.\"\n },\n\t\t\"timezone\": {\n\t\t\t\"The timezone field is required.\"\n }\n\t}\n}", "language": "json" } ] } [/block]
In general, responses follow common HTTP conventions as much as possible. [block:parameters] { "data": { "0-0": "200", "0-1": "OK", "1-0": "201", "1-1": "Created", "1-2": "Returned when POSTing to create a new resource was successful", "0-2": "Everything went okay", "2-0": "400", "2-1": "Bad Request", "2-2": "The request was malformed (missing parameters throw 422)", "3-0": "401", "3-1": "Unauthorized", "3-2": "Invalid credentials supplied", "h-0": "Code", "h-1": "Name", "h-2": "Explanation", "4-0": "422", "4-1": "Unprocessable Entity", "4-2": "A POST data JSON key or alike is malformed or missing", "5-0": "500", "5-1": "Internal Server Error", "5-2": "If you encounter this, please get in touch - this should not happen" }, "cols": 3, "rows": 6 } [/block] If non-existing fields are supplied, they are simply ignored and an error will not be returned (whitelisting approach). ##Successful calls Successful requests that result in 200 response codes will have their data inside a key named "data": [block:code] { "codes": [ { "code": "// 200 OK\n{\n \"data\": \"Response data here\"\n}", "language": "json" } ] } [/block] ##Error messages Whenever an error occurs (e.g. validation), the API will attempt to write the error message inside a key named "error": [block:code] { "codes": [ { "code": "// 400 Bad Request\n{\n\t\"error\": {\n\t\t\"message\": \"Error message here\",\n \"status_code\": 400\n }\n}", "language": "json" } ] } [/block] If more than one error occurs (e.g. multiple fields fail validation), the key will be named "errors" and the relevant messages will be contained in an array: [block:code] { "codes": [ { "code": "// 422 Bad Request\n{\n\t\"errors\": {\n\t\t\"first_name\": {\n\t\t\t\"The first name field is required.\"\n },\n\t\t\"email\": {\n\t\t\t\"The email field is required.\"\n },\n\t\t\"timezone\": {\n\t\t\t\"The timezone field is required.\"\n }\n\t}\n}", "language": "json" } ] } [/block]
{"_id":"57e0f630c4711017001cab66","title":"Pagination","updates":[],"createdAt":"2016-09-20T08:41:20.238Z","hidden":false,"slug":"pagination","next":{"pages":[],"description":""},"order":6,"project":"550ada512188a71900453199","__v":1,"api":{"results":{"codes":[{"status":200,"language":"json","code":"{}","name":""},{"code":"{}","name":"","status":400,"language":"json"}]},"settings":"","auth":"required","params":[],"url":""},"excerpt":"","link_external":false,"parentDoc":null,"sync_unique":"","type":"basic","category":"550bfb5622ccb01700a7946a","githubsync":"","isReference":true,"link_url":"","body":"All top-level resources in the API are paginated. In each paginated response, information related to the previous and next page of the result set is included.\n\nA `?limit` argument can be added to a request, in order to change the amount of results on each page.\n\nTo retrieve the next page of results, use the query param `?page` to specify which page.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Default limit\",\n  \"body\": \"The default limit is set to 50 for most resources in the API.\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Is there more pages?\",\n  \"body\": \"Use the `next_page_url` in the response to determine whether there are additional pages to fetch, i.e. only show a \\\"Load more\\\" button if `next_page_url` is not null.\"\n}\n[/block]\nExample:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl \\\\\\n  -H 'Timekit-App: back-to-the-future' \\\\\\n  -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n  https://api.timekit.io/v2/bookings?limit=3&page=2 \",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nWill return:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"total\\\": 5,\\n  \\\"per_page\\\": \\\"3\\\",\\n  \\\"current_page\\\": 2,\\n  \\\"last_page\\\": 2,\\n  \\\"next_page_url\\\": null,\\n  \\\"prev_page_url\\\": \\\"https://api.timekit.io/v2/bookings?limit=3&page=1\\\",\\n  \\\"from\\\": 4,\\n  \\\"to\\\": 5,\\n  \\\"data\\\": [\\n    {\\n      \\\"id\\\": \\\"c125d175-132a-499e-8beb-87f31378d5ab\\\",\\n      \\\"state\\\": \\\"initialized\\\",\\n      \\\"graph\\\": \\\"instant\\\",\\n      \\\"completed\\\": false,\\n      \\\"created_at\\\": \\\"2016-09-15T11:23:09+0300\\\",\\n      \\\"updated_at\\\": \\\"2016-09-15T11:23:09+0300\\\"\\n    },\\n    {\\n      \\\"id\\\": \\\"06502f41-78b3-4d03-9b6d-4c8b84e360ff\\\",\\n      \\\"state\\\": \\\"initialized\\\",\\n      \\\"graph\\\": \\\"instant\\\",\\n      \\\"completed\\\": false,\\n      \\\"created_at\\\": \\\"2016-09-15T11:23:09+0300\\\",\\n      \\\"updated_at\\\": \\\"2016-09-15T11:23:09+0300\\\"\\n    }\\n  ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]","user":"57c7e8a25754fa1700b121df","version":"550bfb5522ccb01700a79469","childrenPages":[]}

Pagination


All top-level resources in the API are paginated. In each paginated response, information related to the previous and next page of the result set is included. A `?limit` argument can be added to a request, in order to change the amount of results on each page. To retrieve the next page of results, use the query param `?page` to specify which page. [block:callout] { "type": "info", "title": "Default limit", "body": "The default limit is set to 50 for most resources in the API." } [/block] [block:callout] { "type": "success", "title": "Is there more pages?", "body": "Use the `next_page_url` in the response to determine whether there are additional pages to fetch, i.e. only show a \"Load more\" button if `next_page_url` is not null." } [/block] Example: [block:code] { "codes": [ { "code": "curl \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/bookings?limit=3&page=2 ", "language": "curl" } ] } [/block] Will return: [block:code] { "codes": [ { "code": "{\n \"total\": 5,\n \"per_page\": \"3\",\n \"current_page\": 2,\n \"last_page\": 2,\n \"next_page_url\": null,\n \"prev_page_url\": \"https://api.timekit.io/v2/bookings?limit=3&page=1\",\n \"from\": 4,\n \"to\": 5,\n \"data\": [\n {\n \"id\": \"c125d175-132a-499e-8beb-87f31378d5ab\",\n \"state\": \"initialized\",\n \"graph\": \"instant\",\n \"completed\": false,\n \"created_at\": \"2016-09-15T11:23:09+0300\",\n \"updated_at\": \"2016-09-15T11:23:09+0300\"\n },\n {\n \"id\": \"06502f41-78b3-4d03-9b6d-4c8b84e360ff\",\n \"state\": \"initialized\",\n \"graph\": \"instant\",\n \"completed\": false,\n \"created_at\": \"2016-09-15T11:23:09+0300\",\n \"updated_at\": \"2016-09-15T11:23:09+0300\"\n }\n ]\n}", "language": "json" } ] } [/block]
All top-level resources in the API are paginated. In each paginated response, information related to the previous and next page of the result set is included. A `?limit` argument can be added to a request, in order to change the amount of results on each page. To retrieve the next page of results, use the query param `?page` to specify which page. [block:callout] { "type": "info", "title": "Default limit", "body": "The default limit is set to 50 for most resources in the API." } [/block] [block:callout] { "type": "success", "title": "Is there more pages?", "body": "Use the `next_page_url` in the response to determine whether there are additional pages to fetch, i.e. only show a \"Load more\" button if `next_page_url` is not null." } [/block] Example: [block:code] { "codes": [ { "code": "curl \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/bookings?limit=3&page=2 ", "language": "curl" } ] } [/block] Will return: [block:code] { "codes": [ { "code": "{\n \"total\": 5,\n \"per_page\": \"3\",\n \"current_page\": 2,\n \"last_page\": 2,\n \"next_page_url\": null,\n \"prev_page_url\": \"https://api.timekit.io/v2/bookings?limit=3&page=1\",\n \"from\": 4,\n \"to\": 5,\n \"data\": [\n {\n \"id\": \"c125d175-132a-499e-8beb-87f31378d5ab\",\n \"state\": \"initialized\",\n \"graph\": \"instant\",\n \"completed\": false,\n \"created_at\": \"2016-09-15T11:23:09+0300\",\n \"updated_at\": \"2016-09-15T11:23:09+0300\"\n },\n {\n \"id\": \"06502f41-78b3-4d03-9b6d-4c8b84e360ff\",\n \"state\": \"initialized\",\n \"graph\": \"instant\",\n \"completed\": false,\n \"created_at\": \"2016-09-15T11:23:09+0300\",\n \"updated_at\": \"2016-09-15T11:23:09+0300\"\n }\n ]\n}", "language": "json" } ] } [/block]
{"_id":"569e1247ffccd10d00a05acc","slug":"guide-connect-and-setup-google-user","updates":[],"body":"**Table of contents:**\n\n* [Introduction](#introduction)\n* [1. Creating plain resources/users](#1a-creating-plain-resources)\n* [2. Creating resources/users with Google accounts](#1b-creating-resourcesusers-with-google-accounts)\n* [3. Widget credentials](#2-widget-credentials)\n[block:api-header]\n{\n  \"title\": \"Introduction\"\n}\n[/block]\nResources can have calendars, one or multiple, that contains events and bookings. If you're a two-sided marketplace, you can also create resources for your consumers/end-users to make mutual availability checks, but it's not required.\n\n**Onboarding & resource creation**\n\nTimekit can be used without your users even knowing about us, as user/resource creation and provisioning can be done 100% through the API. In the onboarding flow in your app, you can simply add an API call to Timekit where you create the resource (with the email, password, timezone etc. provided through your own screens) and save the resulting API token - more on that below.\n\nWith Google connect, the user would however have to accept OAuth permissions manually, but you can control the callback redirect so users are led back to your own app instead of Timekit.\n\n**User API tokens (credentials)**\n\nWhenever you create a new user/resource (plain user or Google connected), you will receive an API token in the response. We recommend you save this API token in your own database, on your user/resource model, as you will have to use the token for authentication to the Timekit API for all subsequent requests.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"1a. Creating plain resources\"\n}\n[/block]\n1. **Create new resource**\n   *Save the \"email\" and \"token\" from the response for the next API requests*\n   [POST /resources](doc:resources)\n\n2. **Create a new calendar**\n   *The returning calendar ID can be used as a target for creating events/bookings*\n   [POST /calendars](http://developers.timekit.io/docs/calendars-1)\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"1b. Creating resources/users with Google accounts\"\n}\n[/block]\n1. **Connect Google account to create user**\n   *After the callback, save the \"email\" and \"token\" query params for the next API requests*\n   [GET /accounts/google/signup](doc:accountsgooglesignup)\n\n2. **Sync user's Google calendars to Timekit**\n   [GET /accounts/sync](doc:accountssync)\n\n3. **Get user's calendars**\n   *The calendar IDs can be used as targets for creating events/bookings*\n   [GET /calendars](doc:calendars)\n\n4. **Specify which calendars to sync for availability**\n   [PUT /calendars/:id](doc:calendarsid-2)\n\n5. **Perform a sync**\n   [GET /accounts/sync](doc:accountssync)\n[block:api-header]\n{\n  \"title\": \"2. Widget credentials\"\n}\n[/block]\nIf you're planning to use [Booking.js](https://github.com/timekit-io/booking-js), our UI widget, you'll also need to generate a special API token that can be used publicly client-side. These credentials are locked down for only widget relevant endpoints.\n\nThis is done by calling:\n[POST /credentials](doc:credentials)\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Next guide\",\n  \"body\": \"[Continue to the next guide](doc:guide-find-time-book-appointment) and learn how to create and update bookings\"\n}\n[/block]","createdAt":"2016-01-19T10:39:03.336Z","isReference":false,"link_url":"","next":{"description":"","pages":[]},"project":"550ada512188a71900453199","user":"550bf7b2eb24860d00e6a33b","__v":30,"githubsync":"","sync_unique":"","title":"1) Setup resources & calendars","version":"550bfb5522ccb01700a79469","order":0,"excerpt":"","hidden":false,"link_external":false,"parentDoc":null,"type":"basic","api":{"params":[],"results":{"codes":[{"name":"","status":200,"language":"json","code":"{}"},{"language":"json","code":"{}","name":"","status":400}]},"settings":"","url":"","auth":"required"},"category":"56c6e593b935671700ff02af","childrenPages":[]}

1) Setup resources & calendars


**Table of contents:** * [Introduction](#introduction) * [1. Creating plain resources/users](#1a-creating-plain-resources) * [2. Creating resources/users with Google accounts](#1b-creating-resourcesusers-with-google-accounts) * [3. Widget credentials](#2-widget-credentials) [block:api-header] { "title": "Introduction" } [/block] Resources can have calendars, one or multiple, that contains events and bookings. If you're a two-sided marketplace, you can also create resources for your consumers/end-users to make mutual availability checks, but it's not required. **Onboarding & resource creation** Timekit can be used without your users even knowing about us, as user/resource creation and provisioning can be done 100% through the API. In the onboarding flow in your app, you can simply add an API call to Timekit where you create the resource (with the email, password, timezone etc. provided through your own screens) and save the resulting API token - more on that below. With Google connect, the user would however have to accept OAuth permissions manually, but you can control the callback redirect so users are led back to your own app instead of Timekit. **User API tokens (credentials)** Whenever you create a new user/resource (plain user or Google connected), you will receive an API token in the response. We recommend you save this API token in your own database, on your user/resource model, as you will have to use the token for authentication to the Timekit API for all subsequent requests. [block:api-header] { "type": "basic", "title": "1a. Creating plain resources" } [/block] 1. **Create new resource** *Save the "email" and "token" from the response for the next API requests* [POST /resources](doc:resources) 2. **Create a new calendar** *The returning calendar ID can be used as a target for creating events/bookings* [POST /calendars](http://developers.timekit.io/docs/calendars-1) [block:api-header] { "type": "basic", "title": "1b. Creating resources/users with Google accounts" } [/block] 1. **Connect Google account to create user** *After the callback, save the "email" and "token" query params for the next API requests* [GET /accounts/google/signup](doc:accountsgooglesignup) 2. **Sync user's Google calendars to Timekit** [GET /accounts/sync](doc:accountssync) 3. **Get user's calendars** *The calendar IDs can be used as targets for creating events/bookings* [GET /calendars](doc:calendars) 4. **Specify which calendars to sync for availability** [PUT /calendars/:id](doc:calendarsid-2) 5. **Perform a sync** [GET /accounts/sync](doc:accountssync) [block:api-header] { "title": "2. Widget credentials" } [/block] If you're planning to use [Booking.js](https://github.com/timekit-io/booking-js), our UI widget, you'll also need to generate a special API token that can be used publicly client-side. These credentials are locked down for only widget relevant endpoints. This is done by calling: [POST /credentials](doc:credentials) [block:callout] { "type": "success", "title": "Next guide", "body": "[Continue to the next guide](doc:guide-find-time-book-appointment) and learn how to create and update bookings" } [/block]
**Table of contents:** * [Introduction](#introduction) * [1. Creating plain resources/users](#1a-creating-plain-resources) * [2. Creating resources/users with Google accounts](#1b-creating-resourcesusers-with-google-accounts) * [3. Widget credentials](#2-widget-credentials) [block:api-header] { "title": "Introduction" } [/block] Resources can have calendars, one or multiple, that contains events and bookings. If you're a two-sided marketplace, you can also create resources for your consumers/end-users to make mutual availability checks, but it's not required. **Onboarding & resource creation** Timekit can be used without your users even knowing about us, as user/resource creation and provisioning can be done 100% through the API. In the onboarding flow in your app, you can simply add an API call to Timekit where you create the resource (with the email, password, timezone etc. provided through your own screens) and save the resulting API token - more on that below. With Google connect, the user would however have to accept OAuth permissions manually, but you can control the callback redirect so users are led back to your own app instead of Timekit. **User API tokens (credentials)** Whenever you create a new user/resource (plain user or Google connected), you will receive an API token in the response. We recommend you save this API token in your own database, on your user/resource model, as you will have to use the token for authentication to the Timekit API for all subsequent requests. [block:api-header] { "type": "basic", "title": "1a. Creating plain resources" } [/block] 1. **Create new resource** *Save the "email" and "token" from the response for the next API requests* [POST /resources](doc:resources) 2. **Create a new calendar** *The returning calendar ID can be used as a target for creating events/bookings* [POST /calendars](http://developers.timekit.io/docs/calendars-1) [block:api-header] { "type": "basic", "title": "1b. Creating resources/users with Google accounts" } [/block] 1. **Connect Google account to create user** *After the callback, save the "email" and "token" query params for the next API requests* [GET /accounts/google/signup](doc:accountsgooglesignup) 2. **Sync user's Google calendars to Timekit** [GET /accounts/sync](doc:accountssync) 3. **Get user's calendars** *The calendar IDs can be used as targets for creating events/bookings* [GET /calendars](doc:calendars) 4. **Specify which calendars to sync for availability** [PUT /calendars/:id](doc:calendarsid-2) 5. **Perform a sync** [GET /accounts/sync](doc:accountssync) [block:api-header] { "title": "2. Widget credentials" } [/block] If you're planning to use [Booking.js](https://github.com/timekit-io/booking-js), our UI widget, you'll also need to generate a special API token that can be used publicly client-side. These credentials are locked down for only widget relevant endpoints. This is done by calling: [POST /credentials](doc:credentials) [block:callout] { "type": "success", "title": "Next guide", "body": "[Continue to the next guide](doc:guide-find-time-book-appointment) and learn how to create and update bookings" } [/block]
{"_id":"55a40f6253611017004387c1","updates":["5671d4334fec9b0d0089ec95"],"body":"**Table of contents:**\n\n* [Introduction](#introduction)\n* [1. Define business logic as filters](#1-define-business-logic-as-filters)\n* [2. Call the FindTime endpoint](#2-call-the-findtime-endpoint)\n[block:api-header]\n{\n  \"title\": \"Introduction\"\n}\n[/block]\nWe're going to use the API as a backend for appointment calendars, like an AirBnB for X. Different resources can have their own calendar (just like a mentor has appointment slots). We can then search for available time based on rules that the mentors can set themselves, e.g. only available on Tuesdays from 3-5pm and Fridays from 1-4pm. Rules/filters like these will be applied at runtime and are also Timezone aware - in this case, so customers can find timeslots that are within daytime hours if they're located in another country.\n\nIn this exercise, we'll assume our mentor is Doc Brown and our mentee is Marty McFly.\n\nWe're going to assume that we already have [created a resource](http://developers.timekit.io/v2/docs/users) (you dont need to actually do this for now). Follow [the guide](doc:guide-connect-and-setup-google-user) to see how that works. \n\nLet's get to it!\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"1. Define business logic as filters\"\n}\n[/block]\nFirst we'll define some business logic, namely *availability filters*. Filters are passed to the [/findtime](doc:findtime) endpoint as rules that must be satisfied in the query. Filters are quite powerful and can be combined to exclude timeranges - consider it a query language of sorts. Check out the [Filters Reference](doc:find-time-filters) for a complete list and explanation of available filters. \n\nFor our mentor (Doc Brown) <=> mentee (Marty McFly) scenario, let's assume that the mentor is located in Los Angeles and the mentee (who performs the availability search) is in Copenhagen. Furthermore, the mentor has defined \"opening hours\" on Tuesdays from 3-5pm and Fridays from 1-4pm. These constrainst can be written as filters like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// Query filters example\\n\\\"filters\\\": {\\n  \\\"or\\\": [\\n    { \\n      \\\"specific_day_and_time\\\": {\\n      \\t\\\"day\\\": \\\"Tuesday\\\",\\n      \\t\\\"start\\\": 15,\\n      \\t\\\"end\\\": 17,\\n      \\t\\\"timezone\\\": \\\"America/Los_Angeles\\\"\\n    \\t}\\n    },\\n    {\\n      \\\"specific_day_and_time\\\": {\\n        \\\"day\\\": \\\"Friday\\\",\\n        \\\"start\\\": 13,\\n        \\\"end\\\": 16,\\n        \\\"timezone\\\": \\\"America/Los_Angeles\\\"\\n      }\\n    }\\n  ],\\n  \\\"and\\\": [\\n    {\\n      \\\"daytime\\\": {\\n        \\\"timezone\\\": \\\"Europe/Copenhagen\\\"\\n      }\\n    }\\n  ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n*Short explanation*:\nThe first two \"specific_day_and_time\" are inside an OR section, which means that either the first filter or the second filter should be satisfied. The \"daytime\" filter in the AND section means that all results from the OR should also be within that filter. If we had added more filters in the AND, it would have meant that all those filters should be satisfied at the same time (overlapping).\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"Note that we are using a 24-hour clock in the start/end time fields (3:00pm is 15:00)\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Re-using filters across requests\",\n  \"body\": \"You can use [filter collections](doc:findtimefiltercollections) to save your filters in Timekit and reference them in your requests.\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"2. Call the FindTime endpoint\"\n}\n[/block]\nThe Find Time algorithm is where the magic happens. It will essentially loop through the resources calendars and find timeslots that satisfy the supplied filters. You can add multiple resources (and their calendars) that the algorithm must take into account (if the mentee Marty McFly for instance connected his own Google Calendar), which is what we are going to do.\n\n*So, in lay mans terms, this is what we are querying (take a deep breath):*\nFind available timeslots within the next 3 weeks where both Doc Brown and Marty McFly are available for 1 hour, which must be either a Tuesday from 3-5pm or a Friday from 1-4pm (in Los Angeles timezone) and must be within daytime (7am to 11pm in Copenhagen timezone). Phew, that was quite a mouthful.\n\nHere's the cURL request:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example\\n# [POST] /findtime\\ncurl -X POST \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -H 'Timekit-OutputTimestampFormat: Y-m-d H:i:s' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n           \\\"emails\\\": [\\n             \\\"doc.brown@timekit.io\\\",\\n             \\\"marty.mcfly@timekit.io\\\"\\n           ],\\n           \\\"filters\\\": {\\n             \\\"or\\\": [\\n             \\t { \\\"specific_day_and_time\\\": {\\\"day\\\": \\\"Tuesday\\\", \\\"start\\\": 15, \\\"end\\\": 17, \\\"timezone\\\": \\\"America/Los_Angeles\\\"}},\\n               { \\\"specific_day_and_time\\\": {\\\"day\\\": \\\"Friday\\\", \\\"start\\\": 13, \\\"end\\\": 16, \\\"timezone\\\": \\\"America/Los_Angeles\\\"}}\\n             ],\\n             \\\"and\\\": [\\n               { \\\"daytime\\\": {\\\"timezone\\\": \\\"Europe/Copenhagen\\\"}}\\n             ]\\n           },\\n           \\\"future\\\": \\\"4 weeks\\\",\\n           \\\"length\\\": \\\"1 hour\\\"\\n         }' \\\\\\n     https://api.timekit.io/v2/findtime\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"// Request example\\n// [POST] /findtime\\n\\nvar timekit = require('timekit-sdk');\\n\\ntimekit.configure({\\n  app: 'docs'\\n  outputTimestampFormat: 'Y-m-d H:i:s'\\n});\\n\\ntimekit.setUser(doc.brown@timekit.io, FluxCapacitator);\\n\\ntimekit.findTime({\\n  \\\"emails\\\": [\\n    \\\"doc.brown@timekit.io\\\",\\n    \\\"marty.mcfly@timekit.io\\\"\\n  ],\\n  \\\"filters\\\": {\\n    \\\"or\\\": [\\n      { \\\"specific_day_and_time\\\": {\\\"day\\\": \\\"Tuesday\\\", \\\"start\\\": 15, \\\"end\\\": 17, \\\"timezone\\\": \\\"America/Los_Angeles\\\"}},\\n      { \\\"specific_day_and_time\\\": {\\\"day\\\": \\\"Friday\\\", \\\"start\\\": 13, \\\"end\\\": 16, \\\"timezone\\\": \\\"America/Los_Angeles\\\"}}\\n    ],\\n\\t  \\\"and\\\": [\\n\\t    { \\\"daytime\\\": {\\\"timezone\\\": \\\"Europe/Copenhagen\\\"}}\\n    ]\\n  },\\n  \\\"future\\\": \\\"4 weeks\\\",\\n  \\\"length\\\": \\\"1 hour\\\"\\n  }\\n}).then(function(response) {\\n\\tconsole.log(response)\\n})\",\n      \"language\": \"javascript\",\n      \"name\": \"JS SDK\"\n    }\n  ]\n}\n[/block]\nIf it finds any available timeslots, it should return an array of those, looking like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// Response example\\n// [POST] /findtime\\n{\\n\\t\\\"data\\\": [\\n\\t\\t{\\n\\t\\t\\t\\\"start\\\": \\\"2015-07-17 13:00:00\\\",\\n      \\\"end\\\": \\\"2015-07-17 14:00:00\\\"\\n    },\\n    {\\n      \\\"start\\\": \\\"2015-07-24 13:00:00\\\",\\n      \\\"end\\\": \\\"2015-07-24 14:00:00\\\"\\n    },\\n    {\\n      \\\"start\\\": \\\"2015-07-31 13:00:00\\\",\\n      \\\"end\\\": \\\"2015-07-31 14:00:00\\\"\\n    }\\n  ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nNow it's just up to Marty to pick one of the timeslots and book Doc Brown at that time.\n\nGood job, Doc.\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Next guide\",\n  \"body\": \"[Continue to the next guide](doc:building-booking-experiences-with-timekit) and learn how to build an awesome booking experience with Timekit.\"\n}\n[/block]","category":"56c6e593b935671700ff02af","createdAt":"2015-07-13T19:20:02.598Z","isReference":false,"parentDoc":null,"title":"2) Availability search & find time","githubsync":"","next":{"description":"","pages":[]},"project":"550ada512188a71900453199","slug":"guide-find-time-book-appointment","sync_unique":"","user":"550bf7b2eb24860d00e6a33b","api":{"params":[],"results":{"codes":[{"code":"{}","name":"","status":200,"language":"json"},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"","auth":"required"},"excerpt":"","link_external":false,"order":1,"version":"550bfb5522ccb01700a79469","__v":38,"hidden":false,"link_url":"","type":"basic","childrenPages":[]}

2) Availability search & find time


**Table of contents:** * [Introduction](#introduction) * [1. Define business logic as filters](#1-define-business-logic-as-filters) * [2. Call the FindTime endpoint](#2-call-the-findtime-endpoint) [block:api-header] { "title": "Introduction" } [/block] We're going to use the API as a backend for appointment calendars, like an AirBnB for X. Different resources can have their own calendar (just like a mentor has appointment slots). We can then search for available time based on rules that the mentors can set themselves, e.g. only available on Tuesdays from 3-5pm and Fridays from 1-4pm. Rules/filters like these will be applied at runtime and are also Timezone aware - in this case, so customers can find timeslots that are within daytime hours if they're located in another country. In this exercise, we'll assume our mentor is Doc Brown and our mentee is Marty McFly. We're going to assume that we already have [created a resource](http://developers.timekit.io/v2/docs/users) (you dont need to actually do this for now). Follow [the guide](doc:guide-connect-and-setup-google-user) to see how that works. Let's get to it! [block:api-header] { "type": "basic", "title": "1. Define business logic as filters" } [/block] First we'll define some business logic, namely *availability filters*. Filters are passed to the [/findtime](doc:findtime) endpoint as rules that must be satisfied in the query. Filters are quite powerful and can be combined to exclude timeranges - consider it a query language of sorts. Check out the [Filters Reference](doc:find-time-filters) for a complete list and explanation of available filters. For our mentor (Doc Brown) <=> mentee (Marty McFly) scenario, let's assume that the mentor is located in Los Angeles and the mentee (who performs the availability search) is in Copenhagen. Furthermore, the mentor has defined "opening hours" on Tuesdays from 3-5pm and Fridays from 1-4pm. These constrainst can be written as filters like this: [block:code] { "codes": [ { "code": "// Query filters example\n\"filters\": {\n \"or\": [\n { \n \"specific_day_and_time\": {\n \t\"day\": \"Tuesday\",\n \t\"start\": 15,\n \t\"end\": 17,\n \t\"timezone\": \"America/Los_Angeles\"\n \t}\n },\n {\n \"specific_day_and_time\": {\n \"day\": \"Friday\",\n \"start\": 13,\n \"end\": 16,\n \"timezone\": \"America/Los_Angeles\"\n }\n }\n ],\n \"and\": [\n {\n \"daytime\": {\n \"timezone\": \"Europe/Copenhagen\"\n }\n }\n ]\n}", "language": "json" } ] } [/block] *Short explanation*: The first two "specific_day_and_time" are inside an OR section, which means that either the first filter or the second filter should be satisfied. The "daytime" filter in the AND section means that all results from the OR should also be within that filter. If we had added more filters in the AND, it would have meant that all those filters should be satisfied at the same time (overlapping). [block:callout] { "type": "info", "body": "Note that we are using a 24-hour clock in the start/end time fields (3:00pm is 15:00)" } [/block] [block:callout] { "type": "info", "title": "Re-using filters across requests", "body": "You can use [filter collections](doc:findtimefiltercollections) to save your filters in Timekit and reference them in your requests." } [/block] [block:api-header] { "type": "basic", "title": "2. Call the FindTime endpoint" } [/block] The Find Time algorithm is where the magic happens. It will essentially loop through the resources calendars and find timeslots that satisfy the supplied filters. You can add multiple resources (and their calendars) that the algorithm must take into account (if the mentee Marty McFly for instance connected his own Google Calendar), which is what we are going to do. *So, in lay mans terms, this is what we are querying (take a deep breath):* Find available timeslots within the next 3 weeks where both Doc Brown and Marty McFly are available for 1 hour, which must be either a Tuesday from 3-5pm or a Friday from 1-4pm (in Los Angeles timezone) and must be within daytime (7am to 11pm in Copenhagen timezone). Phew, that was quite a mouthful. Here's the cURL request: [block:code] { "codes": [ { "code": "# Request example\n# [POST] /findtime\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -H 'Timekit-OutputTimestampFormat: Y-m-d H:i:s' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"emails\": [\n \"doc.brown@timekit.io\",\n \"marty.mcfly@timekit.io\"\n ],\n \"filters\": {\n \"or\": [\n \t { \"specific_day_and_time\": {\"day\": \"Tuesday\", \"start\": 15, \"end\": 17, \"timezone\": \"America/Los_Angeles\"}},\n { \"specific_day_and_time\": {\"day\": \"Friday\", \"start\": 13, \"end\": 16, \"timezone\": \"America/Los_Angeles\"}}\n ],\n \"and\": [\n { \"daytime\": {\"timezone\": \"Europe/Copenhagen\"}}\n ]\n },\n \"future\": \"4 weeks\",\n \"length\": \"1 hour\"\n }' \\\n https://api.timekit.io/v2/findtime", "language": "curl" }, { "code": "// Request example\n// [POST] /findtime\n\nvar timekit = require('timekit-sdk');\n\ntimekit.configure({\n app: 'docs'\n outputTimestampFormat: 'Y-m-d H:i:s'\n});\n\ntimekit.setUser(doc.brown@timekit.io, FluxCapacitator);\n\ntimekit.findTime({\n \"emails\": [\n \"doc.brown@timekit.io\",\n \"marty.mcfly@timekit.io\"\n ],\n \"filters\": {\n \"or\": [\n { \"specific_day_and_time\": {\"day\": \"Tuesday\", \"start\": 15, \"end\": 17, \"timezone\": \"America/Los_Angeles\"}},\n { \"specific_day_and_time\": {\"day\": \"Friday\", \"start\": 13, \"end\": 16, \"timezone\": \"America/Los_Angeles\"}}\n ],\n\t \"and\": [\n\t { \"daytime\": {\"timezone\": \"Europe/Copenhagen\"}}\n ]\n },\n \"future\": \"4 weeks\",\n \"length\": \"1 hour\"\n }\n}).then(function(response) {\n\tconsole.log(response)\n})", "language": "javascript", "name": "JS SDK" } ] } [/block] If it finds any available timeslots, it should return an array of those, looking like this: [block:code] { "codes": [ { "code": "// Response example\n// [POST] /findtime\n{\n\t\"data\": [\n\t\t{\n\t\t\t\"start\": \"2015-07-17 13:00:00\",\n \"end\": \"2015-07-17 14:00:00\"\n },\n {\n \"start\": \"2015-07-24 13:00:00\",\n \"end\": \"2015-07-24 14:00:00\"\n },\n {\n \"start\": \"2015-07-31 13:00:00\",\n \"end\": \"2015-07-31 14:00:00\"\n }\n ]\n}", "language": "json" } ] } [/block] Now it's just up to Marty to pick one of the timeslots and book Doc Brown at that time. Good job, Doc. [block:callout] { "type": "success", "title": "Next guide", "body": "[Continue to the next guide](doc:building-booking-experiences-with-timekit) and learn how to build an awesome booking experience with Timekit." } [/block]
**Table of contents:** * [Introduction](#introduction) * [1. Define business logic as filters](#1-define-business-logic-as-filters) * [2. Call the FindTime endpoint](#2-call-the-findtime-endpoint) [block:api-header] { "title": "Introduction" } [/block] We're going to use the API as a backend for appointment calendars, like an AirBnB for X. Different resources can have their own calendar (just like a mentor has appointment slots). We can then search for available time based on rules that the mentors can set themselves, e.g. only available on Tuesdays from 3-5pm and Fridays from 1-4pm. Rules/filters like these will be applied at runtime and are also Timezone aware - in this case, so customers can find timeslots that are within daytime hours if they're located in another country. In this exercise, we'll assume our mentor is Doc Brown and our mentee is Marty McFly. We're going to assume that we already have [created a resource](http://developers.timekit.io/v2/docs/users) (you dont need to actually do this for now). Follow [the guide](doc:guide-connect-and-setup-google-user) to see how that works. Let's get to it! [block:api-header] { "type": "basic", "title": "1. Define business logic as filters" } [/block] First we'll define some business logic, namely *availability filters*. Filters are passed to the [/findtime](doc:findtime) endpoint as rules that must be satisfied in the query. Filters are quite powerful and can be combined to exclude timeranges - consider it a query language of sorts. Check out the [Filters Reference](doc:find-time-filters) for a complete list and explanation of available filters. For our mentor (Doc Brown) <=> mentee (Marty McFly) scenario, let's assume that the mentor is located in Los Angeles and the mentee (who performs the availability search) is in Copenhagen. Furthermore, the mentor has defined "opening hours" on Tuesdays from 3-5pm and Fridays from 1-4pm. These constrainst can be written as filters like this: [block:code] { "codes": [ { "code": "// Query filters example\n\"filters\": {\n \"or\": [\n { \n \"specific_day_and_time\": {\n \t\"day\": \"Tuesday\",\n \t\"start\": 15,\n \t\"end\": 17,\n \t\"timezone\": \"America/Los_Angeles\"\n \t}\n },\n {\n \"specific_day_and_time\": {\n \"day\": \"Friday\",\n \"start\": 13,\n \"end\": 16,\n \"timezone\": \"America/Los_Angeles\"\n }\n }\n ],\n \"and\": [\n {\n \"daytime\": {\n \"timezone\": \"Europe/Copenhagen\"\n }\n }\n ]\n}", "language": "json" } ] } [/block] *Short explanation*: The first two "specific_day_and_time" are inside an OR section, which means that either the first filter or the second filter should be satisfied. The "daytime" filter in the AND section means that all results from the OR should also be within that filter. If we had added more filters in the AND, it would have meant that all those filters should be satisfied at the same time (overlapping). [block:callout] { "type": "info", "body": "Note that we are using a 24-hour clock in the start/end time fields (3:00pm is 15:00)" } [/block] [block:callout] { "type": "info", "title": "Re-using filters across requests", "body": "You can use [filter collections](doc:findtimefiltercollections) to save your filters in Timekit and reference them in your requests." } [/block] [block:api-header] { "type": "basic", "title": "2. Call the FindTime endpoint" } [/block] The Find Time algorithm is where the magic happens. It will essentially loop through the resources calendars and find timeslots that satisfy the supplied filters. You can add multiple resources (and their calendars) that the algorithm must take into account (if the mentee Marty McFly for instance connected his own Google Calendar), which is what we are going to do. *So, in lay mans terms, this is what we are querying (take a deep breath):* Find available timeslots within the next 3 weeks where both Doc Brown and Marty McFly are available for 1 hour, which must be either a Tuesday from 3-5pm or a Friday from 1-4pm (in Los Angeles timezone) and must be within daytime (7am to 11pm in Copenhagen timezone). Phew, that was quite a mouthful. Here's the cURL request: [block:code] { "codes": [ { "code": "# Request example\n# [POST] /findtime\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -H 'Timekit-OutputTimestampFormat: Y-m-d H:i:s' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"emails\": [\n \"doc.brown@timekit.io\",\n \"marty.mcfly@timekit.io\"\n ],\n \"filters\": {\n \"or\": [\n \t { \"specific_day_and_time\": {\"day\": \"Tuesday\", \"start\": 15, \"end\": 17, \"timezone\": \"America/Los_Angeles\"}},\n { \"specific_day_and_time\": {\"day\": \"Friday\", \"start\": 13, \"end\": 16, \"timezone\": \"America/Los_Angeles\"}}\n ],\n \"and\": [\n { \"daytime\": {\"timezone\": \"Europe/Copenhagen\"}}\n ]\n },\n \"future\": \"4 weeks\",\n \"length\": \"1 hour\"\n }' \\\n https://api.timekit.io/v2/findtime", "language": "curl" }, { "code": "// Request example\n// [POST] /findtime\n\nvar timekit = require('timekit-sdk');\n\ntimekit.configure({\n app: 'docs'\n outputTimestampFormat: 'Y-m-d H:i:s'\n});\n\ntimekit.setUser(doc.brown@timekit.io, FluxCapacitator);\n\ntimekit.findTime({\n \"emails\": [\n \"doc.brown@timekit.io\",\n \"marty.mcfly@timekit.io\"\n ],\n \"filters\": {\n \"or\": [\n { \"specific_day_and_time\": {\"day\": \"Tuesday\", \"start\": 15, \"end\": 17, \"timezone\": \"America/Los_Angeles\"}},\n { \"specific_day_and_time\": {\"day\": \"Friday\", \"start\": 13, \"end\": 16, \"timezone\": \"America/Los_Angeles\"}}\n ],\n\t \"and\": [\n\t { \"daytime\": {\"timezone\": \"Europe/Copenhagen\"}}\n ]\n },\n \"future\": \"4 weeks\",\n \"length\": \"1 hour\"\n }\n}).then(function(response) {\n\tconsole.log(response)\n})", "language": "javascript", "name": "JS SDK" } ] } [/block] If it finds any available timeslots, it should return an array of those, looking like this: [block:code] { "codes": [ { "code": "// Response example\n// [POST] /findtime\n{\n\t\"data\": [\n\t\t{\n\t\t\t\"start\": \"2015-07-17 13:00:00\",\n \"end\": \"2015-07-17 14:00:00\"\n },\n {\n \"start\": \"2015-07-24 13:00:00\",\n \"end\": \"2015-07-24 14:00:00\"\n },\n {\n \"start\": \"2015-07-31 13:00:00\",\n \"end\": \"2015-07-31 14:00:00\"\n }\n ]\n}", "language": "json" } ] } [/block] Now it's just up to Marty to pick one of the timeslots and book Doc Brown at that time. Good job, Doc. [block:callout] { "type": "success", "title": "Next guide", "body": "[Continue to the next guide](doc:building-booking-experiences-with-timekit) and learn how to build an awesome booking experience with Timekit." } [/block]
{"_id":"5804dd1992398f0f00e77532","parentDoc":null,"project":"550ada512188a71900453199","version":"550bfb5522ccb01700a79469","createdAt":"2016-10-17T14:15:53.576Z","next":{"description":"","pages":[]},"type":"basic","__v":1,"body":"**Table of contents:**\n\n* [Introduction](#introduction)\n* [Understanding \"graphs\"](#understanding-graphs)\n* [Understanding \"actions\"](#understanding-actions)\n* [1. Creating a booking](#1-creating-a-booking)\n* [2a. Performing an action: decline](#2a-performing-an-action-decline)\n* [2b. Performing an action: confirm](#2b-performing-an-action-confirm)\n* [3. Retrieving booking data](#3-retrieving-booking-data)\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Introduction\"\n}\n[/block]\nTimekit's booking engine is a hosted and flexible solution to handle booking flows for your app. Bookings can follow different [graphs](http://developers.timekit.io/docs/building-booking-experiences-with-timekit#understanding-graphs), which are a pre-defined set of steps that can trigger actions upon state change, such as sending out emails or trigger webhooks. The booking engine has graphs for many different use cases, such as instant bookings, bookings that need confirmation, bookings that involve a payment step, bookings that involve groups or classes etc.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Understanding \\\"graphs\\\"\"\n}\n[/block]\nGraphs are the \"blueprints\" that bookings are based on. They define different actions and transitions that bookings can go through, based on your business logic. If you are looking to set up a 1-to-1 booking flow, currently there are two graphs available:\n\n1) `instant` - Instant booking where new bookings are auto-confirmed\n2) `confirm_decline` - New bookings start in a tentative state and you can either confirm or decline them.\n\nIf you are looking to set up a 1-to-many, or group, booking flow, you should read our guide on [groups and classes](http://developers.timekit.io/v2/docs/4-groups-and-classes).\n\nWhen you create a booking, you chose which flow graph it should follow. A JSON representation of the flow graphs can be retrieved by calling [this](doc:bookingsgraphsid) endpoint and a Graphviz PNG representation of the flow by calling [this](doc:bookingsgraphsnamediagram) instead.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Groups or classes?\",\n  \"body\": \"If you need multiple users to book the same resources (like signing up to a class or group session), you should take a look at our \\\"[Groups and classes](http://developers.timekit.io/v2/docs/4-groups-and-classes)\\\" guide, where we go through how to set up a group booking flow.\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Understanding \\\"actions\\\"\"\n}\n[/block]\nActions are transitions between steps in your graph, such as confirming, cancelling or rescheduling a booking. Some actions are triggered manually by you through the API, where others are autoplaying (internal steps) that happen automatically in a sequence. For instance, when you call the \"confirm\" action, the booking engine could automatically create a calendar event, send out an email notification and trigger a webhook before reaching the \"confirmed\" state.\n\nEvery time you want to move a booking further down the graph, you trigger the next action using the  [[PUT] /bookings/:id/:action](doc:bookingsidaction) endpoint. When creating a booking you can trigger the first action at the same time, saving you an additional [[PUT] /bookings/:id/:action](doc:bookingsidaction) request.\n\nAs an example, when creating a booking, you also need to supply event details and customer info, though this information isn't actually used by the first action in the graph. The data supplied to the `event` parameter will be used to create an actual event in Timekit (internally calling [[POST] /events](doc:events-1)) and the data in `customer` will be saved as a linked entity (only \"name\" and \"email\" is required).\n\n## Action settings\n\nSome actions have settings that you can pass to them, e.g. whether an \"autoplay\" action in the call-chain should be enabled or not (sending out emails, trigger webhooks etc). These actions take inputs through a key, which usually corresponds to the actions name. See the reference for the individual graph for an overview.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"1. Creating a booking\"\n}\n[/block]\nFor this guide, we will create a booking based on the `confirm_decline` graph. \nHere's a diagram representation of how that looks:\n\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/f78347e-confirm_decline_graph.png\",\n        \"confirm_decline_graph.png\",\n        821,\n        1808,\n        \"#e3ebeb\"\n      ],\n      \"sizing\": \"smart\",\n      \"caption\": \"Confirm/decline flow graph\"\n    }\n  ]\n}\n[/block]\nYou can read an explanation [here](doc:bookingsgraphsnamediagram)\n\nOkay, let's get to it - start by calling [[POST] /bookings](doc:bookings-1) with this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example (replace :calendar-id)\\n# [POST] /bookings\\ncurl -X POST \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n          \\\"graph\\\": \\\"confirm_decline\\\",\\n          \\\"action\\\": \\\"create\\\",\\n          \\\"event\\\": {\\n            \\\"start\\\": \\\"2015-03-01T08:00:00+00:00\\\",\\n            \\\"end\\\": \\\"2015-03-01T13:00:00+00:00\\\",\\n            \\\"what\\\": \\\"Mens haircut\\\",\\n            \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n            \\\"calendar_id\\\": \\\":calendar-id\\\",\\n            \\\"description\\\": \\\"Please arrive 10 minutes before you time begin\\\"\\n          },\\n          \\\"customer\\\": {\\n            \\\"name\\\": \\\"Marty McFly\\\",\\n            \\\"email\\\": \\\"marty.mcfly@timekit.io\\\",\\n            \\\"phone\\\": \\\"1-591-001-5403\\\",\\n            \\\"voip\\\": \\\"McFly\\\",\\n            \\\"timezone\\\": \\\"America/Los_Angeles\\\"\\n          }\\n        }' \\\\\\n     https://api.timekit.io/v2/bookings\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"// Request example\\n// [POST] /bookings\\n\\nvar timekit = require('timekit-sdk');\\n\\ntimekit.configure({\\n  app: 'docs',\\n  outputTimestampFormat: 'Y-m-d H:i:s'\\n});\\n\\ntimekit.setUser('doc.brown@timekit.io', 'FluxCapacitator');\\n\\ntimekit.createBooking({\\n  \\\"graph\\\": \\\"confirm_decline\\\",\\n  \\\"action\\\": \\\"create\\\",\\n  \\\"event\\\": {\\n    \\\"start\\\": \\\"2015-03-01T08:00:00+00:00\\\",\\n    \\\"end\\\": \\\"2015-03-01T13:00:00+00:00\\\",\\n    \\\"what\\\": \\\"Mens haircut\\\",\\n    \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n    \\\"calendar_id\\\": \\\":calendar-id\\\",\\n    \\\"description\\\": \\\"Please arrive 10 minutes before you time begin\\\"\\n  },\\n  \\\"customer\\\": {\\n    \\\"name\\\": \\\"Marty McFly\\\",\\n    \\\"email\\\": \\\"marty.mcfly@timekit.io\\\",\\n    \\\"phone\\\": \\\"1-591-001-5403\\\",\\n    \\\"voip\\\": \\\"McFly\\\",\\n    \\\"timezone\\\": \\\"America/Los_Angeles\\\"\\n  }\\n}).then(function(response) {\\n\\tconsole.log(response)\\n})\",\n      \"language\": \"javascript\",\n      \"name\": \"JS SDK\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"API calls and resource context\",\n  \"body\": \"Note that all API requests should be done in context of the host/provider resource (using the corresponding Authentication headers). This ensures that the booking belongs to them and can be retrieved later.\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Availability and timeslots\",\n  \"body\": \"Note that retrieving availability for a host/provider using FindTime is the exact same process as always. Chosen timeslot info are simply passed to the \\\"event\\\" key instead of calling [[POST] /events](doc:evetnts-1) directly\"\n}\n[/block]\nThis will 1) create a new booking entity and 2) perform the \"create\" action on it immediately. The create action requires \"event\" and \"customer\" data, as it will save that to the Timekit DB.\n\nYou should get a response similar to this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// Response example\\n// [POST] /bookings\\n{\\n  \\\"data\\\": {\\n    \\\"id\\\": \\\"58190fc6-1ec0-4ebb-b627-7ce6aa9fc703\\\",\\n    \\\"graph\\\": \\\"confirm_decline\\\",\\n    \\\"state\\\": \\\"tentative\\\",\\n    \\\"completed\\\": false,\\n    \\\"possible_actions\\\": [\\n      \\\"decline\\\",\\n      \\\"confirm\\\"\\n    ],\\n    \\\"created_at\\\": \\\"2016-02-11T11:58:45+0100\\\",\\n    \\\"updated_at\\\": \\\"2016-02-11T11:58:47+0100\\\",\\n    \\\"attributes\\\": {\\n      \\\"event_info\\\": {\\n        \\\"start\\\": \\\"2015-03-01T08:00:00+00:00\\\",\\n        \\\"end\\\": \\\"2015-03-01T13:00:00+00:00\\\",\\n        \\\"what\\\": \\\"Mens haircut\\\",\\n        \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n        \\\"description\\\": \\\"Please arrive 10 minutes before you time begin\\\"\\n      }\\n    },\\n    \\\"calendar\\\": {\\n      \\\"id\\\": \\\"c91c5d04-2a57-46c0-ab35-e489dadf132e\\\",\\n      \\\"name\\\": \\\"My calendar\\\",\\n      \\\"display_name\\\": \\\"My calendar\\\",\\n      \\\"description\\\": \\\"Ut adipisci non autem cum ut id.\\\",\\n      \\\"foregroundcolor\\\": \\\"#25d6be\\\",\\n      \\\"backgroundcolor\\\": \\\"#ea1cb8\\\",\\n      \\\"created_at\\\": \\\"2016-02-15T13:21:42+0100\\\",\\n      \\\"updated_at\\\": \\\"2016-02-15T13:21:42+0100\\\"\\n    },\\n    \\\"customers\\\": [\\n      {\\n        \\\"id\\\": \\\"a728e860-99c7-4009-8843-7d9ac5d7f53f\\\",\\n        \\\"name\\\": \\\"Marty McFly\\\",\\n        \\\"email\\\": \\\"marty.mcfly@timekit.io\\\",\\n        \\\"phone\\\": \\\"1-591-001-5403\\\",\\n        \\\"voip\\\": \\\"McFly\\\",\\n        \\\"timezone\\\": \\\"America/Los_Angeles\\\"\\n      }\\n    ]\\n  }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nThe booking is now in the \"tentative\" state. If we take a look at the diagram again, we can see that it has performed the following autoplay actions:\n1) `save_customer_data` - validate and save the customer info provided in the \"customer\" key\n2) `save_booking_data` - validate and save the event info provided in the \"event\" key (this will be used for creating the calendar event later)\n3) `send_confirm_decline_email_to_owner` - sends out an email to the owner of the booking (service provider) based on a email template\n\nThe email sent looks something like this:\n\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/2nlMmHQsQJKJGN5X67DY_Screen%20Shot%202016-02-11%20at%2012.40.50.png\",\n        \"Screen Shot 2016-02-11 at 12.40.50.png\",\n        \"1100\",\n        \"1014\",\n        \"#d45c5c\",\n        \"\"\n      ],\n      \"caption\": \"Notification email sent to owner\"\n    }\n  ]\n}\n[/block]\nThe \"Confirm\" and \"Decline\" buttons currently links to a page in the new Timekit Admin that will call the relevant [[PUT] /bookings/:id/:action](doc:bookingsidaction) endpoint when visited. It's a simple solution for those who just want to get quickly up and running (e.g. using Booking.js without a custom integration). If you want to sent your own emails, you can disable the default ones when you create the booking and use [webhooks](http://developers.timekit.io/docs/graphs-reference) to know when a booking has been created. Disabling the action looks like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example (replace :calendar-id)\\n# [POST] /bookings\\ncurl -X POST \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n          \\\"graph\\\": \\\"confirm_decline\\\",\\n          \\\"action\\\": \\\"create\\\",\\n          \\\"send_confirm_decline_email_to_owner\\\": {\\n          \\t\\\"enabled\\\": false\\n          }\\n          ...\\n        }' \\\\\\n     https://api.timekit.io/v2/bookings\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nFor now, we'll keep it enabled to prove the point.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"2a. Performing an action: decline\"\n}\n[/block]\nIf you have your own admin panel, where your users/resources can manage their bookings, allowing them to confirm/decline a booking is very easy through the API. You can decline a booking with the PUT [/bookings/:id/:action](doc:bookingsidaction) endpoint using the `decline` action. It looks like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example (replace :id)\\n# [PUT] /bookings/:id/decline\\ncurl -X POST \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n          \\\"notify_customer_declined_by_email\\\": {\\n\\t\\t\\t\\t    \\\"message\\\": \\\"Sorry, I'm not available at that location\\\"\\n\\t\\t\\t\\t  }\\n        }' \\\\\\n     https://api.timekit.io/v2/bookings/:id/decline\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"// Request example\\n// [PUT] /bookings/:id/decline\\n\\nvar timekit = require('timekit-sdk');\\n\\ntimekit.configure({\\n  app: 'docs'\\n  outputTimestampFormat: 'Y-m-d H:i:s'\\n});\\n\\ntimekit.setUser(doc.brown@timekit.io, FluxCapacitator);\\n\\ntimekit.updateBooking({\\n  \\\"notify_customer_declined_by_email\\\": {\\n    \\\"message\\\": \\\"Sorry, I'm not available at that location\\\"\\n  }\\n}).then(function(response) {\\n\\tconsole.log(response)\\n})\",\n      \"language\": \"javascript\",\n      \"name\": \"JS SDK\"\n    }\n  ]\n}\n[/block]\nThis will trigger the decline steps as shown in the diagram and when it hits the `notify_customer_declined_by_email` step, it will use the message you provide in the request and add it to the email.\n\nThe resulting email will look something like this:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/8RldL5eSRiuX7JiMbKPs_Screen%20Shot%202016-02-11%20at%2013.18.41.png\",\n        \"Screen Shot 2016-02-11 at 13.18.41.png\",\n        \"1116\",\n        \"982\",\n        \"#d0d2d4\",\n        \"\"\n      ],\n      \"caption\": \"Notification email sent to customer\"\n    }\n  ]\n}\n[/block]\nIf you need to customize this step and use your own emails, you should read about [Emails & webhooks](doc:graphs-reference).\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"2b. Performing an action: confirm\"\n}\n[/block]\nIf we assumed that the owner wanted to confirm the booking instead, you would call [[PUT] /bookings/:id/confirm](doc:bookingsidaction) and the booking would follow the steps in that branch.\n\nThe main action of interest here is the `create_event`. This will, as expected, create a Timekit event with the data provided in the \"event\" key when you created the booking (similar to calling [[POST] /events](doc:events-1)). This plays nicely together with FindTime availability, as the event now blocks for the availability like you'd normally expect.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"If Doc Brown (mentor) is connected using a Google Calendar, he would automatically have an event pushed into his calendar. If Marty McFly (mentee) also is created as Timekit user/resource with a Google account, he would get a event invite directly inside Google calendar that he can RSVP to.\",\n  \"title\": \"Creating events in Google calendars\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"3. Retrieving booking data\"\n}\n[/block]\nThe booking engine saves a complete audit trail of all actions and state changes performed throughout the lifetime of a booking. Call the [[GET] /bookings](doc:bookings-2) to get all your bookings and their associated meta-data.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// Response example\\n// [GET] /bookings\\n{\\n  \\\"data\\\": {\\n    \\\"id\\\": \\\"f68979ff-27da-4afd-8d0c-847f9340331b\\\",\\n    \\\"state\\\": \\\"declined\\\",\\n    \\\"graph\\\": \\\"confirm_decline\\\",\\n    \\\"completed\\\": true,\\n    \\\"possible_actions\\\": [],\\n    \\\"created_at\\\": \\\"2016-02-11T12:39:45+0100\\\",\\n    \\\"updated_at\\\": \\\"2016-02-11T13:12:01+0100\\\",\\n    \\\"attributes\\\": {\\n      \\\"event_info\\\": {\\n        \\\"start\\\": \\\"2015-01-01T09:00:00+0100\\\",\\n        \\\"end\\\": \\\"2015-01-01T14:00:00+0100\\\",\\n        \\\"what\\\": \\\"Mens haircut\\\",\\n        \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n        \\\"description\\\": \\\"Please arrive 10 minutes before you time begin\\\"\\n      }\\n    },\\n    \\\"calendar\\\": {\\n      \\\"id\\\": \\\"c91c5d04-2a57-46c0-ab35-e489dadf132e\\\",\\n      \\\"name\\\": \\\"My calendar\\\",\\n      \\\"display_name\\\": \\\"My calendar\\\",\\n      \\\"description\\\": \\\"Ut adipisci non autem cum ut id.\\\",\\n      \\\"foregroundcolor\\\": \\\"#25d6be\\\",\\n      \\\"backgroundcolor\\\": \\\"#ea1cb8\\\",\\n      \\\"created_at\\\": \\\"2016-02-15T13:21:42+0100\\\",\\n      \\\"updated_at\\\": \\\"2016-02-15T13:21:42+0100\\\"\\n    },\\n    \\\"customers\\\": [\\n      {\\n        \\\"id\\\": \\\"a728e860-99c7-4009-8843-7d9ac5d7f53f\\\",\\n        \\\"name\\\": \\\"Marty McFly\\\",\\n        \\\"email\\\": \\\"marty.mcfly@timekit.io\\\",\\n        \\\"phone\\\": \\\"1-591-001-5403\\\",\\n        \\\"voip\\\": \\\"McFly\\\",\\n        \\\"timezone\\\": \\\"America/Los_Angeles\\\"\\n      }\\n    ],\\n    \\\"logs\\\": [\\n      {\\n        \\\"description\\\": \\\"Changed state to: created\\\",\\n        \\\"success\\\": \\\"true\\\",\\n        \\\"state\\\": \\\"created\\\",\\n        \\\"data\\\": \\\"[]\\\",\\n        \\\"created_at\\\": \\\"2016-02-11T12:39:45+0100\\\"\\n      },\\n      {\\n        \\\"description\\\": \\\"Changed state to: customer_data_saved\\\",\\n        \\\"success\\\": \\\"true\\\",\\n        \\\"state\\\": \\\"customer_data_saved\\\",\\n        \\\"data\\\": \\\"[]\\\",\\n        \\\"created_at\\\": \\\"2016-02-11T12:39:45+0100\\\"\\n      },\\n      {\\n        \\\"description\\\": \\\"Updated booking object with success\\\",\\n        \\\"success\\\": \\\"true\\\",\\n        \\\"state\\\": \\\"customer_data_saved\\\",\\n        \\\"data\\\": \\\"[]\\\",\\n        \\\"created_at\\\": \\\"2016-02-11T12:39:45+0100\\\"\\n      },\\n      {\\n        \\\"description\\\": \\\"Changed state to: booking_data_saved\\\",\\n        \\\"success\\\": \\\"true\\\",\\n        \\\"state\\\": \\\"booking_data_saved\\\",\\n        \\\"data\\\": \\\"[]\\\",\\n        \\\"created_at\\\": \\\"2016-02-11T12:39:45+0100\\\"\\n      },\\n      {\\n        \\\"description\\\": \\\"Trying to send (confirm/decline) email to owner (timebirdcphtest@gmail.com)...\\\",\\n        \\\"success\\\": \\\"true\\\",\\n        \\\"state\\\": \\\"booking_data_saved\\\",\\n        \\\"data\\\": \\\"[]\\\",\\n        \\\"created_at\\\": \\\"2016-02-11T12:39:45+0100\\\"\\n      },\\n      {\\n        \\\"description\\\": \\\"Email sent to timebirdcphtest@gmail.com!\\\",\\n        \\\"success\\\": \\\"true\\\",\\n        \\\"state\\\": \\\"booking_data_saved\\\",\\n        \\\"data\\\": \\\"[]\\\",\\n        \\\"created_at\\\": \\\"2016-02-11T12:39:46+0100\\\"\\n      },\\n      {\\n        \\\"description\\\": \\\"Changed state to: notified_owner_by_action_email\\\",\\n        \\\"success\\\": \\\"true\\\",\\n        \\\"state\\\": \\\"notified_owner_by_action_email\\\",\\n        \\\"data\\\": \\\"[]\\\",\\n        \\\"created_at\\\": \\\"2016-02-11T12:39:46+0100\\\"\\n      },\\n      {\\n        \\\"description\\\": \\\"Changed state to: tentative\\\",\\n        \\\"success\\\": \\\"true\\\",\\n        \\\"state\\\": \\\"tentative\\\",\\n        \\\"data\\\": \\\"[]\\\",\\n        \\\"created_at\\\": \\\"2016-02-11T12:39:46+0100\\\"\\n      },\\n      {\\n        \\\"description\\\": \\\"Booking was rejected by: timebirdcphtest@gmail.com\\\",\\n        \\\"success\\\": \\\"true\\\",\\n        \\\"state\\\": \\\"tentative\\\",\\n        \\\"data\\\": \\\"[]\\\",\\n        \\\"created_at\\\": \\\"2016-02-11T13:11:59+0100\\\"\\n      },\\n      {\\n        \\\"description\\\": \\\"Changed state to: declining\\\",\\n        \\\"success\\\": \\\"true\\\",\\n        \\\"state\\\": \\\"declining\\\",\\n        \\\"data\\\": \\\"[]\\\",\\n        \\\"created_at\\\": \\\"2016-02-11T13:11:59+0100\\\"\\n      },\\n      {\\n        \\\"description\\\": \\\"Trying to send (declined notification) email to customer (marty.mcfly@timekit.io)...\\\",\\n        \\\"success\\\": \\\"true\\\",\\n        \\\"state\\\": \\\"declining\\\",\\n        \\\"data\\\": \\\"[]\\\",\\n        \\\"created_at\\\": \\\"2016-02-11T13:11:59+0100\\\"\\n      },\\n      {\\n        \\\"description\\\": \\\"Email sent to marty.mcfly@timekit.io!\\\",\\n        \\\"success\\\": \\\"true\\\",\\n        \\\"state\\\": \\\"declining\\\",\\n        \\\"data\\\": \\\"[]\\\",\\n        \\\"created_at\\\": \\\"2016-02-11T13:12:01+0100\\\"\\n      },\\n      {\\n        \\\"description\\\": \\\"Changed state to: notified_customer_declined_by_email\\\",\\n        \\\"success\\\": \\\"true\\\",\\n        \\\"state\\\": \\\"notified_customer_declined_by_email\\\",\\n        \\\"data\\\": \\\"[]\\\",\\n        \\\"created_at\\\": \\\"2016-02-11T13:12:01+0100\\\"\\n      },\\n      {\\n        \\\"description\\\": \\\"Changed state to: declined\\\",\\n        \\\"success\\\": \\\"true\\\",\\n        \\\"state\\\": \\\"declined\\\",\\n        \\\"data\\\": \\\"[]\\\",\\n        \\\"created_at\\\": \\\"2016-02-11T13:12:01+0100\\\"\\n      }\\n    ]\\n  }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nGreat scott, you've finished our guide! We hope that our booking engine makes sense to you and that you are ready to dive in. If not, hit us up on the chat and we'll help you get started.\n\nAlso if you haven't already, we recommend that you read these guides too:\n\n- [1) Setup resources & calendars](doc:guide-connect-and-setup-google-user) \n- [2) Availability search & find time](doc:guide-find-time-book-appointment) \n- [3) Groups and classes](doc:4-groups-and-classes)","githubsync":"","slug":"building-booking-experiences-with-timekit","title":"3) Creating & managing bookings","updates":[],"user":"57c7e8a25754fa1700b121df","excerpt":"","hidden":false,"isReference":false,"link_external":false,"link_url":"","order":2,"sync_unique":"","api":{"results":{"codes":[{"name":"","status":200,"language":"json","code":"{}"},{"status":400,"language":"json","code":"{}","name":""}]},"auth":"required","params":[],"url":"","settings":""},"category":"56c6e593b935671700ff02af","childrenPages":[]}

3) Creating & managing bookings


**Table of contents:** * [Introduction](#introduction) * [Understanding "graphs"](#understanding-graphs) * [Understanding "actions"](#understanding-actions) * [1. Creating a booking](#1-creating-a-booking) * [2a. Performing an action: decline](#2a-performing-an-action-decline) * [2b. Performing an action: confirm](#2b-performing-an-action-confirm) * [3. Retrieving booking data](#3-retrieving-booking-data) [block:api-header] { "type": "basic", "title": "Introduction" } [/block] Timekit's booking engine is a hosted and flexible solution to handle booking flows for your app. Bookings can follow different [graphs](http://developers.timekit.io/docs/building-booking-experiences-with-timekit#understanding-graphs), which are a pre-defined set of steps that can trigger actions upon state change, such as sending out emails or trigger webhooks. The booking engine has graphs for many different use cases, such as instant bookings, bookings that need confirmation, bookings that involve a payment step, bookings that involve groups or classes etc. [block:api-header] { "type": "basic", "title": "Understanding \"graphs\"" } [/block] Graphs are the "blueprints" that bookings are based on. They define different actions and transitions that bookings can go through, based on your business logic. If you are looking to set up a 1-to-1 booking flow, currently there are two graphs available: 1) `instant` - Instant booking where new bookings are auto-confirmed 2) `confirm_decline` - New bookings start in a tentative state and you can either confirm or decline them. If you are looking to set up a 1-to-many, or group, booking flow, you should read our guide on [groups and classes](http://developers.timekit.io/v2/docs/4-groups-and-classes). When you create a booking, you chose which flow graph it should follow. A JSON representation of the flow graphs can be retrieved by calling [this](doc:bookingsgraphsid) endpoint and a Graphviz PNG representation of the flow by calling [this](doc:bookingsgraphsnamediagram) instead. [block:callout] { "type": "info", "title": "Groups or classes?", "body": "If you need multiple users to book the same resources (like signing up to a class or group session), you should take a look at our \"[Groups and classes](http://developers.timekit.io/v2/docs/4-groups-and-classes)\" guide, where we go through how to set up a group booking flow." } [/block] [block:api-header] { "type": "basic", "title": "Understanding \"actions\"" } [/block] Actions are transitions between steps in your graph, such as confirming, cancelling or rescheduling a booking. Some actions are triggered manually by you through the API, where others are autoplaying (internal steps) that happen automatically in a sequence. For instance, when you call the "confirm" action, the booking engine could automatically create a calendar event, send out an email notification and trigger a webhook before reaching the "confirmed" state. Every time you want to move a booking further down the graph, you trigger the next action using the [[PUT] /bookings/:id/:action](doc:bookingsidaction) endpoint. When creating a booking you can trigger the first action at the same time, saving you an additional [[PUT] /bookings/:id/:action](doc:bookingsidaction) request. As an example, when creating a booking, you also need to supply event details and customer info, though this information isn't actually used by the first action in the graph. The data supplied to the `event` parameter will be used to create an actual event in Timekit (internally calling [[POST] /events](doc:events-1)) and the data in `customer` will be saved as a linked entity (only "name" and "email" is required). ## Action settings Some actions have settings that you can pass to them, e.g. whether an "autoplay" action in the call-chain should be enabled or not (sending out emails, trigger webhooks etc). These actions take inputs through a key, which usually corresponds to the actions name. See the reference for the individual graph for an overview. [block:api-header] { "type": "basic", "title": "1. Creating a booking" } [/block] For this guide, we will create a booking based on the `confirm_decline` graph. Here's a diagram representation of how that looks: [block:image] { "images": [ { "image": [ "https://files.readme.io/f78347e-confirm_decline_graph.png", "confirm_decline_graph.png", 821, 1808, "#e3ebeb" ], "sizing": "smart", "caption": "Confirm/decline flow graph" } ] } [/block] You can read an explanation [here](doc:bookingsgraphsnamediagram) Okay, let's get to it - start by calling [[POST] /bookings](doc:bookings-1) with this: [block:code] { "codes": [ { "code": "# Request example (replace :calendar-id)\n# [POST] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"graph\": \"confirm_decline\",\n \"action\": \"create\",\n \"event\": {\n \"start\": \"2015-03-01T08:00:00+00:00\",\n \"end\": \"2015-03-01T13:00:00+00:00\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \":calendar-id\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n },\n \"customer\": {\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n }' \\\n https://api.timekit.io/v2/bookings", "language": "curl" }, { "code": "// Request example\n// [POST] /bookings\n\nvar timekit = require('timekit-sdk');\n\ntimekit.configure({\n app: 'docs',\n outputTimestampFormat: 'Y-m-d H:i:s'\n});\n\ntimekit.setUser('doc.brown@timekit.io', 'FluxCapacitator');\n\ntimekit.createBooking({\n \"graph\": \"confirm_decline\",\n \"action\": \"create\",\n \"event\": {\n \"start\": \"2015-03-01T08:00:00+00:00\",\n \"end\": \"2015-03-01T13:00:00+00:00\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \":calendar-id\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n },\n \"customer\": {\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n}).then(function(response) {\n\tconsole.log(response)\n})", "language": "javascript", "name": "JS SDK" } ] } [/block] [block:callout] { "type": "info", "title": "API calls and resource context", "body": "Note that all API requests should be done in context of the host/provider resource (using the corresponding Authentication headers). This ensures that the booking belongs to them and can be retrieved later." } [/block] [block:callout] { "type": "info", "title": "Availability and timeslots", "body": "Note that retrieving availability for a host/provider using FindTime is the exact same process as always. Chosen timeslot info are simply passed to the \"event\" key instead of calling [[POST] /events](doc:evetnts-1) directly" } [/block] This will 1) create a new booking entity and 2) perform the "create" action on it immediately. The create action requires "event" and "customer" data, as it will save that to the Timekit DB. You should get a response similar to this: [block:code] { "codes": [ { "code": "// Response example\n// [POST] /bookings\n{\n \"data\": {\n \"id\": \"58190fc6-1ec0-4ebb-b627-7ce6aa9fc703\",\n \"graph\": \"confirm_decline\",\n \"state\": \"tentative\",\n \"completed\": false,\n \"possible_actions\": [\n \"decline\",\n \"confirm\"\n ],\n \"created_at\": \"2016-02-11T11:58:45+0100\",\n \"updated_at\": \"2016-02-11T11:58:47+0100\",\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2015-03-01T08:00:00+00:00\",\n \"end\": \"2015-03-01T13:00:00+00:00\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n }\n },\n \"calendar\": {\n \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n \"name\": \"My calendar\",\n \"display_name\": \"My calendar\",\n \"description\": \"Ut adipisci non autem cum ut id.\",\n \"foregroundcolor\": \"#25d6be\",\n \"backgroundcolor\": \"#ea1cb8\",\n \"created_at\": \"2016-02-15T13:21:42+0100\",\n \"updated_at\": \"2016-02-15T13:21:42+0100\"\n },\n \"customers\": [\n {\n \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n ]\n }\n}", "language": "json" } ] } [/block] The booking is now in the "tentative" state. If we take a look at the diagram again, we can see that it has performed the following autoplay actions: 1) `save_customer_data` - validate and save the customer info provided in the "customer" key 2) `save_booking_data` - validate and save the event info provided in the "event" key (this will be used for creating the calendar event later) 3) `send_confirm_decline_email_to_owner` - sends out an email to the owner of the booking (service provider) based on a email template The email sent looks something like this: [block:image] { "images": [ { "image": [ "https://files.readme.io/2nlMmHQsQJKJGN5X67DY_Screen%20Shot%202016-02-11%20at%2012.40.50.png", "Screen Shot 2016-02-11 at 12.40.50.png", "1100", "1014", "#d45c5c", "" ], "caption": "Notification email sent to owner" } ] } [/block] The "Confirm" and "Decline" buttons currently links to a page in the new Timekit Admin that will call the relevant [[PUT] /bookings/:id/:action](doc:bookingsidaction) endpoint when visited. It's a simple solution for those who just want to get quickly up and running (e.g. using Booking.js without a custom integration). If you want to sent your own emails, you can disable the default ones when you create the booking and use [webhooks](http://developers.timekit.io/docs/graphs-reference) to know when a booking has been created. Disabling the action looks like this: [block:code] { "codes": [ { "code": "# Request example (replace :calendar-id)\n# [POST] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"graph\": \"confirm_decline\",\n \"action\": \"create\",\n \"send_confirm_decline_email_to_owner\": {\n \t\"enabled\": false\n }\n ...\n }' \\\n https://api.timekit.io/v2/bookings", "language": "curl" } ] } [/block] For now, we'll keep it enabled to prove the point. [block:api-header] { "type": "basic", "title": "2a. Performing an action: decline" } [/block] If you have your own admin panel, where your users/resources can manage their bookings, allowing them to confirm/decline a booking is very easy through the API. You can decline a booking with the PUT [/bookings/:id/:action](doc:bookingsidaction) endpoint using the `decline` action. It looks like this: [block:code] { "codes": [ { "code": "# Request example (replace :id)\n# [PUT] /bookings/:id/decline\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"notify_customer_declined_by_email\": {\n\t\t\t\t \"message\": \"Sorry, I'm not available at that location\"\n\t\t\t\t }\n }' \\\n https://api.timekit.io/v2/bookings/:id/decline", "language": "curl" }, { "code": "// Request example\n// [PUT] /bookings/:id/decline\n\nvar timekit = require('timekit-sdk');\n\ntimekit.configure({\n app: 'docs'\n outputTimestampFormat: 'Y-m-d H:i:s'\n});\n\ntimekit.setUser(doc.brown@timekit.io, FluxCapacitator);\n\ntimekit.updateBooking({\n \"notify_customer_declined_by_email\": {\n \"message\": \"Sorry, I'm not available at that location\"\n }\n}).then(function(response) {\n\tconsole.log(response)\n})", "language": "javascript", "name": "JS SDK" } ] } [/block] This will trigger the decline steps as shown in the diagram and when it hits the `notify_customer_declined_by_email` step, it will use the message you provide in the request and add it to the email. The resulting email will look something like this: [block:image] { "images": [ { "image": [ "https://files.readme.io/8RldL5eSRiuX7JiMbKPs_Screen%20Shot%202016-02-11%20at%2013.18.41.png", "Screen Shot 2016-02-11 at 13.18.41.png", "1116", "982", "#d0d2d4", "" ], "caption": "Notification email sent to customer" } ] } [/block] If you need to customize this step and use your own emails, you should read about [Emails & webhooks](doc:graphs-reference). [block:api-header] { "type": "basic", "title": "2b. Performing an action: confirm" } [/block] If we assumed that the owner wanted to confirm the booking instead, you would call [[PUT] /bookings/:id/confirm](doc:bookingsidaction) and the booking would follow the steps in that branch. The main action of interest here is the `create_event`. This will, as expected, create a Timekit event with the data provided in the "event" key when you created the booking (similar to calling [[POST] /events](doc:events-1)). This plays nicely together with FindTime availability, as the event now blocks for the availability like you'd normally expect. [block:callout] { "type": "info", "body": "If Doc Brown (mentor) is connected using a Google Calendar, he would automatically have an event pushed into his calendar. If Marty McFly (mentee) also is created as Timekit user/resource with a Google account, he would get a event invite directly inside Google calendar that he can RSVP to.", "title": "Creating events in Google calendars" } [/block] [block:api-header] { "type": "basic", "title": "3. Retrieving booking data" } [/block] The booking engine saves a complete audit trail of all actions and state changes performed throughout the lifetime of a booking. Call the [[GET] /bookings](doc:bookings-2) to get all your bookings and their associated meta-data. [block:code] { "codes": [ { "code": "// Response example\n// [GET] /bookings\n{\n \"data\": {\n \"id\": \"f68979ff-27da-4afd-8d0c-847f9340331b\",\n \"state\": \"declined\",\n \"graph\": \"confirm_decline\",\n \"completed\": true,\n \"possible_actions\": [],\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\",\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2015-01-01T09:00:00+0100\",\n \"end\": \"2015-01-01T14:00:00+0100\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n }\n },\n \"calendar\": {\n \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n \"name\": \"My calendar\",\n \"display_name\": \"My calendar\",\n \"description\": \"Ut adipisci non autem cum ut id.\",\n \"foregroundcolor\": \"#25d6be\",\n \"backgroundcolor\": \"#ea1cb8\",\n \"created_at\": \"2016-02-15T13:21:42+0100\",\n \"updated_at\": \"2016-02-15T13:21:42+0100\"\n },\n \"customers\": [\n {\n \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n ],\n \"logs\": [\n {\n \"description\": \"Changed state to: created\",\n \"success\": \"true\",\n \"state\": \"created\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:45+0100\"\n },\n {\n \"description\": \"Changed state to: customer_data_saved\",\n \"success\": \"true\",\n \"state\": \"customer_data_saved\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:45+0100\"\n },\n {\n \"description\": \"Updated booking object with success\",\n \"success\": \"true\",\n \"state\": \"customer_data_saved\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:45+0100\"\n },\n {\n \"description\": \"Changed state to: booking_data_saved\",\n \"success\": \"true\",\n \"state\": \"booking_data_saved\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:45+0100\"\n },\n {\n \"description\": \"Trying to send (confirm/decline) email to owner (timebirdcphtest@gmail.com)...\",\n \"success\": \"true\",\n \"state\": \"booking_data_saved\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:45+0100\"\n },\n {\n \"description\": \"Email sent to timebirdcphtest@gmail.com!\",\n \"success\": \"true\",\n \"state\": \"booking_data_saved\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:46+0100\"\n },\n {\n \"description\": \"Changed state to: notified_owner_by_action_email\",\n \"success\": \"true\",\n \"state\": \"notified_owner_by_action_email\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:46+0100\"\n },\n {\n \"description\": \"Changed state to: tentative\",\n \"success\": \"true\",\n \"state\": \"tentative\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:46+0100\"\n },\n {\n \"description\": \"Booking was rejected by: timebirdcphtest@gmail.com\",\n \"success\": \"true\",\n \"state\": \"tentative\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T13:11:59+0100\"\n },\n {\n \"description\": \"Changed state to: declining\",\n \"success\": \"true\",\n \"state\": \"declining\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T13:11:59+0100\"\n },\n {\n \"description\": \"Trying to send (declined notification) email to customer (marty.mcfly@timekit.io)...\",\n \"success\": \"true\",\n \"state\": \"declining\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T13:11:59+0100\"\n },\n {\n \"description\": \"Email sent to marty.mcfly@timekit.io!\",\n \"success\": \"true\",\n \"state\": \"declining\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T13:12:01+0100\"\n },\n {\n \"description\": \"Changed state to: notified_customer_declined_by_email\",\n \"success\": \"true\",\n \"state\": \"notified_customer_declined_by_email\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T13:12:01+0100\"\n },\n {\n \"description\": \"Changed state to: declined\",\n \"success\": \"true\",\n \"state\": \"declined\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T13:12:01+0100\"\n }\n ]\n }\n}", "language": "json" } ] } [/block] Great scott, you've finished our guide! We hope that our booking engine makes sense to you and that you are ready to dive in. If not, hit us up on the chat and we'll help you get started. Also if you haven't already, we recommend that you read these guides too: - [1) Setup resources & calendars](doc:guide-connect-and-setup-google-user) - [2) Availability search & find time](doc:guide-find-time-book-appointment) - [3) Groups and classes](doc:4-groups-and-classes)
**Table of contents:** * [Introduction](#introduction) * [Understanding "graphs"](#understanding-graphs) * [Understanding "actions"](#understanding-actions) * [1. Creating a booking](#1-creating-a-booking) * [2a. Performing an action: decline](#2a-performing-an-action-decline) * [2b. Performing an action: confirm](#2b-performing-an-action-confirm) * [3. Retrieving booking data](#3-retrieving-booking-data) [block:api-header] { "type": "basic", "title": "Introduction" } [/block] Timekit's booking engine is a hosted and flexible solution to handle booking flows for your app. Bookings can follow different [graphs](http://developers.timekit.io/docs/building-booking-experiences-with-timekit#understanding-graphs), which are a pre-defined set of steps that can trigger actions upon state change, such as sending out emails or trigger webhooks. The booking engine has graphs for many different use cases, such as instant bookings, bookings that need confirmation, bookings that involve a payment step, bookings that involve groups or classes etc. [block:api-header] { "type": "basic", "title": "Understanding \"graphs\"" } [/block] Graphs are the "blueprints" that bookings are based on. They define different actions and transitions that bookings can go through, based on your business logic. If you are looking to set up a 1-to-1 booking flow, currently there are two graphs available: 1) `instant` - Instant booking where new bookings are auto-confirmed 2) `confirm_decline` - New bookings start in a tentative state and you can either confirm or decline them. If you are looking to set up a 1-to-many, or group, booking flow, you should read our guide on [groups and classes](http://developers.timekit.io/v2/docs/4-groups-and-classes). When you create a booking, you chose which flow graph it should follow. A JSON representation of the flow graphs can be retrieved by calling [this](doc:bookingsgraphsid) endpoint and a Graphviz PNG representation of the flow by calling [this](doc:bookingsgraphsnamediagram) instead. [block:callout] { "type": "info", "title": "Groups or classes?", "body": "If you need multiple users to book the same resources (like signing up to a class or group session), you should take a look at our \"[Groups and classes](http://developers.timekit.io/v2/docs/4-groups-and-classes)\" guide, where we go through how to set up a group booking flow." } [/block] [block:api-header] { "type": "basic", "title": "Understanding \"actions\"" } [/block] Actions are transitions between steps in your graph, such as confirming, cancelling or rescheduling a booking. Some actions are triggered manually by you through the API, where others are autoplaying (internal steps) that happen automatically in a sequence. For instance, when you call the "confirm" action, the booking engine could automatically create a calendar event, send out an email notification and trigger a webhook before reaching the "confirmed" state. Every time you want to move a booking further down the graph, you trigger the next action using the [[PUT] /bookings/:id/:action](doc:bookingsidaction) endpoint. When creating a booking you can trigger the first action at the same time, saving you an additional [[PUT] /bookings/:id/:action](doc:bookingsidaction) request. As an example, when creating a booking, you also need to supply event details and customer info, though this information isn't actually used by the first action in the graph. The data supplied to the `event` parameter will be used to create an actual event in Timekit (internally calling [[POST] /events](doc:events-1)) and the data in `customer` will be saved as a linked entity (only "name" and "email" is required). ## Action settings Some actions have settings that you can pass to them, e.g. whether an "autoplay" action in the call-chain should be enabled or not (sending out emails, trigger webhooks etc). These actions take inputs through a key, which usually corresponds to the actions name. See the reference for the individual graph for an overview. [block:api-header] { "type": "basic", "title": "1. Creating a booking" } [/block] For this guide, we will create a booking based on the `confirm_decline` graph. Here's a diagram representation of how that looks: [block:image] { "images": [ { "image": [ "https://files.readme.io/f78347e-confirm_decline_graph.png", "confirm_decline_graph.png", 821, 1808, "#e3ebeb" ], "sizing": "smart", "caption": "Confirm/decline flow graph" } ] } [/block] You can read an explanation [here](doc:bookingsgraphsnamediagram) Okay, let's get to it - start by calling [[POST] /bookings](doc:bookings-1) with this: [block:code] { "codes": [ { "code": "# Request example (replace :calendar-id)\n# [POST] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"graph\": \"confirm_decline\",\n \"action\": \"create\",\n \"event\": {\n \"start\": \"2015-03-01T08:00:00+00:00\",\n \"end\": \"2015-03-01T13:00:00+00:00\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \":calendar-id\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n },\n \"customer\": {\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n }' \\\n https://api.timekit.io/v2/bookings", "language": "curl" }, { "code": "// Request example\n// [POST] /bookings\n\nvar timekit = require('timekit-sdk');\n\ntimekit.configure({\n app: 'docs',\n outputTimestampFormat: 'Y-m-d H:i:s'\n});\n\ntimekit.setUser('doc.brown@timekit.io', 'FluxCapacitator');\n\ntimekit.createBooking({\n \"graph\": \"confirm_decline\",\n \"action\": \"create\",\n \"event\": {\n \"start\": \"2015-03-01T08:00:00+00:00\",\n \"end\": \"2015-03-01T13:00:00+00:00\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \":calendar-id\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n },\n \"customer\": {\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n}).then(function(response) {\n\tconsole.log(response)\n})", "language": "javascript", "name": "JS SDK" } ] } [/block] [block:callout] { "type": "info", "title": "API calls and resource context", "body": "Note that all API requests should be done in context of the host/provider resource (using the corresponding Authentication headers). This ensures that the booking belongs to them and can be retrieved later." } [/block] [block:callout] { "type": "info", "title": "Availability and timeslots", "body": "Note that retrieving availability for a host/provider using FindTime is the exact same process as always. Chosen timeslot info are simply passed to the \"event\" key instead of calling [[POST] /events](doc:evetnts-1) directly" } [/block] This will 1) create a new booking entity and 2) perform the "create" action on it immediately. The create action requires "event" and "customer" data, as it will save that to the Timekit DB. You should get a response similar to this: [block:code] { "codes": [ { "code": "// Response example\n// [POST] /bookings\n{\n \"data\": {\n \"id\": \"58190fc6-1ec0-4ebb-b627-7ce6aa9fc703\",\n \"graph\": \"confirm_decline\",\n \"state\": \"tentative\",\n \"completed\": false,\n \"possible_actions\": [\n \"decline\",\n \"confirm\"\n ],\n \"created_at\": \"2016-02-11T11:58:45+0100\",\n \"updated_at\": \"2016-02-11T11:58:47+0100\",\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2015-03-01T08:00:00+00:00\",\n \"end\": \"2015-03-01T13:00:00+00:00\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n }\n },\n \"calendar\": {\n \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n \"name\": \"My calendar\",\n \"display_name\": \"My calendar\",\n \"description\": \"Ut adipisci non autem cum ut id.\",\n \"foregroundcolor\": \"#25d6be\",\n \"backgroundcolor\": \"#ea1cb8\",\n \"created_at\": \"2016-02-15T13:21:42+0100\",\n \"updated_at\": \"2016-02-15T13:21:42+0100\"\n },\n \"customers\": [\n {\n \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n ]\n }\n}", "language": "json" } ] } [/block] The booking is now in the "tentative" state. If we take a look at the diagram again, we can see that it has performed the following autoplay actions: 1) `save_customer_data` - validate and save the customer info provided in the "customer" key 2) `save_booking_data` - validate and save the event info provided in the "event" key (this will be used for creating the calendar event later) 3) `send_confirm_decline_email_to_owner` - sends out an email to the owner of the booking (service provider) based on a email template The email sent looks something like this: [block:image] { "images": [ { "image": [ "https://files.readme.io/2nlMmHQsQJKJGN5X67DY_Screen%20Shot%202016-02-11%20at%2012.40.50.png", "Screen Shot 2016-02-11 at 12.40.50.png", "1100", "1014", "#d45c5c", "" ], "caption": "Notification email sent to owner" } ] } [/block] The "Confirm" and "Decline" buttons currently links to a page in the new Timekit Admin that will call the relevant [[PUT] /bookings/:id/:action](doc:bookingsidaction) endpoint when visited. It's a simple solution for those who just want to get quickly up and running (e.g. using Booking.js without a custom integration). If you want to sent your own emails, you can disable the default ones when you create the booking and use [webhooks](http://developers.timekit.io/docs/graphs-reference) to know when a booking has been created. Disabling the action looks like this: [block:code] { "codes": [ { "code": "# Request example (replace :calendar-id)\n# [POST] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"graph\": \"confirm_decline\",\n \"action\": \"create\",\n \"send_confirm_decline_email_to_owner\": {\n \t\"enabled\": false\n }\n ...\n }' \\\n https://api.timekit.io/v2/bookings", "language": "curl" } ] } [/block] For now, we'll keep it enabled to prove the point. [block:api-header] { "type": "basic", "title": "2a. Performing an action: decline" } [/block] If you have your own admin panel, where your users/resources can manage their bookings, allowing them to confirm/decline a booking is very easy through the API. You can decline a booking with the PUT [/bookings/:id/:action](doc:bookingsidaction) endpoint using the `decline` action. It looks like this: [block:code] { "codes": [ { "code": "# Request example (replace :id)\n# [PUT] /bookings/:id/decline\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"notify_customer_declined_by_email\": {\n\t\t\t\t \"message\": \"Sorry, I'm not available at that location\"\n\t\t\t\t }\n }' \\\n https://api.timekit.io/v2/bookings/:id/decline", "language": "curl" }, { "code": "// Request example\n// [PUT] /bookings/:id/decline\n\nvar timekit = require('timekit-sdk');\n\ntimekit.configure({\n app: 'docs'\n outputTimestampFormat: 'Y-m-d H:i:s'\n});\n\ntimekit.setUser(doc.brown@timekit.io, FluxCapacitator);\n\ntimekit.updateBooking({\n \"notify_customer_declined_by_email\": {\n \"message\": \"Sorry, I'm not available at that location\"\n }\n}).then(function(response) {\n\tconsole.log(response)\n})", "language": "javascript", "name": "JS SDK" } ] } [/block] This will trigger the decline steps as shown in the diagram and when it hits the `notify_customer_declined_by_email` step, it will use the message you provide in the request and add it to the email. The resulting email will look something like this: [block:image] { "images": [ { "image": [ "https://files.readme.io/8RldL5eSRiuX7JiMbKPs_Screen%20Shot%202016-02-11%20at%2013.18.41.png", "Screen Shot 2016-02-11 at 13.18.41.png", "1116", "982", "#d0d2d4", "" ], "caption": "Notification email sent to customer" } ] } [/block] If you need to customize this step and use your own emails, you should read about [Emails & webhooks](doc:graphs-reference). [block:api-header] { "type": "basic", "title": "2b. Performing an action: confirm" } [/block] If we assumed that the owner wanted to confirm the booking instead, you would call [[PUT] /bookings/:id/confirm](doc:bookingsidaction) and the booking would follow the steps in that branch. The main action of interest here is the `create_event`. This will, as expected, create a Timekit event with the data provided in the "event" key when you created the booking (similar to calling [[POST] /events](doc:events-1)). This plays nicely together with FindTime availability, as the event now blocks for the availability like you'd normally expect. [block:callout] { "type": "info", "body": "If Doc Brown (mentor) is connected using a Google Calendar, he would automatically have an event pushed into his calendar. If Marty McFly (mentee) also is created as Timekit user/resource with a Google account, he would get a event invite directly inside Google calendar that he can RSVP to.", "title": "Creating events in Google calendars" } [/block] [block:api-header] { "type": "basic", "title": "3. Retrieving booking data" } [/block] The booking engine saves a complete audit trail of all actions and state changes performed throughout the lifetime of a booking. Call the [[GET] /bookings](doc:bookings-2) to get all your bookings and their associated meta-data. [block:code] { "codes": [ { "code": "// Response example\n// [GET] /bookings\n{\n \"data\": {\n \"id\": \"f68979ff-27da-4afd-8d0c-847f9340331b\",\n \"state\": \"declined\",\n \"graph\": \"confirm_decline\",\n \"completed\": true,\n \"possible_actions\": [],\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\",\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2015-01-01T09:00:00+0100\",\n \"end\": \"2015-01-01T14:00:00+0100\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n }\n },\n \"calendar\": {\n \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n \"name\": \"My calendar\",\n \"display_name\": \"My calendar\",\n \"description\": \"Ut adipisci non autem cum ut id.\",\n \"foregroundcolor\": \"#25d6be\",\n \"backgroundcolor\": \"#ea1cb8\",\n \"created_at\": \"2016-02-15T13:21:42+0100\",\n \"updated_at\": \"2016-02-15T13:21:42+0100\"\n },\n \"customers\": [\n {\n \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n ],\n \"logs\": [\n {\n \"description\": \"Changed state to: created\",\n \"success\": \"true\",\n \"state\": \"created\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:45+0100\"\n },\n {\n \"description\": \"Changed state to: customer_data_saved\",\n \"success\": \"true\",\n \"state\": \"customer_data_saved\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:45+0100\"\n },\n {\n \"description\": \"Updated booking object with success\",\n \"success\": \"true\",\n \"state\": \"customer_data_saved\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:45+0100\"\n },\n {\n \"description\": \"Changed state to: booking_data_saved\",\n \"success\": \"true\",\n \"state\": \"booking_data_saved\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:45+0100\"\n },\n {\n \"description\": \"Trying to send (confirm/decline) email to owner (timebirdcphtest@gmail.com)...\",\n \"success\": \"true\",\n \"state\": \"booking_data_saved\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:45+0100\"\n },\n {\n \"description\": \"Email sent to timebirdcphtest@gmail.com!\",\n \"success\": \"true\",\n \"state\": \"booking_data_saved\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:46+0100\"\n },\n {\n \"description\": \"Changed state to: notified_owner_by_action_email\",\n \"success\": \"true\",\n \"state\": \"notified_owner_by_action_email\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:46+0100\"\n },\n {\n \"description\": \"Changed state to: tentative\",\n \"success\": \"true\",\n \"state\": \"tentative\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T12:39:46+0100\"\n },\n {\n \"description\": \"Booking was rejected by: timebirdcphtest@gmail.com\",\n \"success\": \"true\",\n \"state\": \"tentative\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T13:11:59+0100\"\n },\n {\n \"description\": \"Changed state to: declining\",\n \"success\": \"true\",\n \"state\": \"declining\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T13:11:59+0100\"\n },\n {\n \"description\": \"Trying to send (declined notification) email to customer (marty.mcfly@timekit.io)...\",\n \"success\": \"true\",\n \"state\": \"declining\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T13:11:59+0100\"\n },\n {\n \"description\": \"Email sent to marty.mcfly@timekit.io!\",\n \"success\": \"true\",\n \"state\": \"declining\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T13:12:01+0100\"\n },\n {\n \"description\": \"Changed state to: notified_customer_declined_by_email\",\n \"success\": \"true\",\n \"state\": \"notified_customer_declined_by_email\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T13:12:01+0100\"\n },\n {\n \"description\": \"Changed state to: declined\",\n \"success\": \"true\",\n \"state\": \"declined\",\n \"data\": \"[]\",\n \"created_at\": \"2016-02-11T13:12:01+0100\"\n }\n ]\n }\n}", "language": "json" } ] } [/block] Great scott, you've finished our guide! We hope that our booking engine makes sense to you and that you are ready to dive in. If not, hit us up on the chat and we'll help you get started. Also if you haven't already, we recommend that you read these guides too: - [1) Setup resources & calendars](doc:guide-connect-and-setup-google-user) - [2) Availability search & find time](doc:guide-find-time-book-appointment) - [3) Groups and classes](doc:4-groups-and-classes)
{"_id":"57ea3d2766130b1700056e8e","link_url":"","project":"550ada512188a71900453199","version":"550bfb5522ccb01700a79469","__v":1,"excerpt":"","parentDoc":null,"user":"57c7e8a25754fa1700b121df","category":"56c6e593b935671700ff02af","createdAt":"2016-09-27T09:34:31.778Z","githubsync":"","slug":"4-groups-and-classes","title":"4) Group & class bookings","type":"basic","order":3,"api":{"results":{"codes":[{"status":200,"language":"json","code":"{}","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","auth":"required","params":[],"url":""},"body":"**Table of contents:**\n\n* [Introduction](#introduction) \n* [What is a group booking?](#what-is-a-group-booking)\n* [1. Define availability](#1-define-availability)\n* [2a. Sign up for a group booking](#2a-sign-up-for-a-group-booking)\n* [2b. Integrating payments for signups](#2b-integrating-payments-for-signups)\n* [3. Cancellations](#3-cancellations)\n* [4. Manage a group booking](#4-manage-a-group-booking)\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Introduction\"\n}\n[/block]\nThrough the `/booking` endpoint you are able to set up groups and classes, so that multiple customers can sign up for the same event. You can use the Timekit API to manage everything from your meetings and sales calls to your webinars and yoga classes. Speaking of! Let's have a look at how you would use Timekit to manage the yoga studio you've always wanted to open:\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"What is a group booking?\"\n}\n[/block]\nTimekit offer many different booking flows, each represented as a graph. When you are working with group bookings, you are interacting with two different graphs: The `group_owner` graph and either the `group_customer` or the `group_customer_payment` graph.\n\nThe `group_owner` graph is used to reserve a time slot in the owners's calendar and make it available for customers to book as a group. You can think of this as the owners availability. If you are going to offer a yoga class on Friday at 7pm, you simply need to add a booking using the `group_owner` graph. \n\nWhen a group booking is set up, customers can book a seat. This is done using the `group_customer` graph or, if your system involves payments, the `group_customer_payment` graph. Customers can sign up for a group booking until there are no available seats left.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"1. Define availability\"\n}\n[/block]\nBefore customers can sign up to our yoga class, we need to configure our availability as owner. This is done by adding a owner booking using the `group_owner` graph.\n\n## Set up availability\n\nFor this example Doc Brown (Yes! That Doc Brown) is offering a yoga class with 20 seats, at his yoga studio on Sesame St. Middleburg, FL 32068, USA. It takes place on September 30, 2016 at 9:00 - and you don't want to miss it!\n\nUsing the `group_owner` graph, we can use the following request to set up the class:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example (replace :calendar-id)\\n# [POST] /bookings\\ncurl -X POST \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n          \\\"graph\\\": \\\"group_owner\\\",\\n          \\\"action\\\": \\\"create\\\",\\n          \\\"settings\\\": {\\n            \\\"max_seats\\\": 20\\n          },\\n          \\\"event\\\": {\\n            \\\"start\\\": \\\"2016-09-30T08:00:00+00:00\\\",\\n            \\\"end\\\": \\\"2016-09-30T09:00:00+00:00\\\",\\n            \\\"what\\\": \\\"Doc Brown's Friday Yoga Class\\\",\\n            \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n            \\\"calendar_id\\\": \\\"replace-with-id\\\",\\n            \\\"description\\\": \\\"Please arrive 10 minutes before classes begin\\\"\\n          }\\n        }' \\\\\\n     https://api.timekit.io/v2/bookings\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\n*Notice that we are using [iso6800](https://en.wikipedia.org/wiki/ISO_8601) standard for the timestamp (this is [configurable](https://dash.readme.io/project/timekit/v2/docs/types--formatting)).*\n\nNow, the yoga class will be available for customers to sign up for. Hurry up before it sells out!\n\nOptionally, you can specify some basic rules for when customers can sign up to your groups. Doc wants you to cancel at least a day before the class begins, book it no more than 14 days in advance and no later than 2 hours before. We can set it up like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example (replace :calendar-id)\\n# [POST] /bookings\\ncurl -X POST \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n          \\\"graph\\\": \\\"group_owner\\\",\\n          \\\"action\\\": \\\"create\\\",\\n          \\\"settings\\\": {\\n            \\\"max_seats\\\": 20,\\n            \\\"min_cancel_time\\\": \\\"1 day\\\",\\n            \\\"min_booking_time\\\": \\\"2 hours\\\",\\n            \\\"max_booking_time\\\": \\\"14 days\\\"\\n          },\\n          \\\"event\\\": {\\n            \\\"start\\\": \\\"2016-09-30T08:00:00+00:00\\\",\\n            \\\"end\\\": \\\"2016-09-30T09:00:00+00:00\\\",\\n            \\\"what\\\": \\\"Doc Brown's Friday Yoga Class\\\",\\n            \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n            \\\"calendar_id\\\": \\\"replace-with-id\\\",\\n            \\\"description\\\": \\\"Please arrive 10 minutes before classes begin\\\"\\n          }\\n        }' \\\\\\n     https://api.timekit.io/v2/bookings\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Setting up multiple groups at once?\",\n  \"body\": \"If you are setting up multiple groups at once, say a yoga class every Friday for the next 10 weeks, you will need to call the `/bookings` endpoint 10 times. We are working on a version of our [`/findtime`](http://developers.timekit.io/docs/findtime) endpoint to allow you to query availability in bulk.\"\n}\n[/block]\n## Query availability\n\nWhen customers visit Doc's website, we want them to see all his classes. Technically speaking, we want to list all his group bookings that are still in a `tentative` state - meaning that they are neither completed, nor cancelled. We can use the `/bookings/groups` endpoint to query Doc's availability. That looks like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example\\n# [GET] /bookings/search\\ncurl -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     https://api.timekit.io/v2/bookings/groups\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nAnd will return something like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"data\\\": [\\n    {\\n      \\\"id\\\": \\\"0dad9c8f-2801-4b6f-b898-7c69063bed0d\\\",\\n      \\\"state\\\": \\\"tentative\\\",\\n      \\\"graph\\\": \\\"group_owner\\\",\\n      \\\"completed\\\": false,\\n      \\\"created_at\\\": \\\"2016-02-11T12:39:45+0100\\\",\\n      \\\"updated_at\\\": \\\"2016-02-11T13:12:01+0100\\\",\\n      \\\"attributes\\\": {\\n        \\\"event_info\\\": {\\n          \\\"start\\\": \\\"2016-09-30T08:00:00+00:00\\\",\\n          \\\"end\\\": \\\"2016-09-30T09:00:00+00:00\\\",\\n          \\\"what\\\": \\\"Doc Brown's Friday Yoga Class\\\",\\n          \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n          \\\"calendar_id\\\": \\\"replace-with-id\\\",\\n          \\\"description\\\": \\\"Please arrive 10 minutes before classes begin\\\"\\n        },\\n        \\\"group_booking\\\": {\\n          \\\"current_seats\\\": 0,\\n          \\\"max_seats\\\": 20,\\n        }\\n      }\\n    },\\n    {\\n      \\\"id\\\": \\\"a1ebdd9d-db42-4cd3-a915-0202a034284a\\\",\\n      \\\"state\\\": \\\"tentative\\\",\\n      \\\"graph\\\": \\\"group_owner\\\",\\n      \\\"completed\\\": false,\\n      \\\"created_at\\\": \\\"2016-02-11T12:39:45+0100\\\",\\n      \\\"updated_at\\\": \\\"2016-02-11T13:12:01+0100\\\",\\n      \\\"attributes\\\": {\\n        \\\"event_info\\\": {\\n          \\\"start\\\": \\\"2016-10-07T08:00:00+00:00\\\",\\n          \\\"end\\\": \\\"2016-10-07T09:00:00+00:00\\\",\\n          \\\"what\\\": \\\"Doc Brown's Friday Yoga Class\\\",\\n          \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n          \\\"calendar_id\\\": \\\"replace-with-id\\\",\\n          \\\"description\\\": \\\"Please arrive 10 minutes before classes begin\\\"\\n        },\\n        \\\"group_booking\\\": {\\n          \\\"current_seats\\\": 0,\\n          \\\"max_seats\\\": 20,\\n        }\\n      }\\n    }\\n  ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nLooks like no one signed up so far!? Guess there's still time to sign up. Let's do it!\n\nYou can optionally specify a `start` and `end` query parameter, to only get bookings within a given period of time.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Is it safe to expose booking data?\",\n  \"body\": \"If you publicly expose information about a group booking (similar to what we do in our Booking.js widget), you should always use the `/bookings/groups` endpoint, as opposed to the regular `/booking` endpoint. This endpoint excludes all sensitive information about the group, such as customer information.\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"2a. Sign up for a group booking\"\n}\n[/block]\nIt appears that a certain Marty McFly is interesting in joining the yoga class. I'm sure Doc will be pleased to know, so let's sign him up using the `group_customer` graph:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example\\n# [POST] /bookings\\ncurl -X POST \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n          \\\"graph\\\": \\\"group_customer\\\",\\n          \\\"action\\\": \\\"create\\\",\\n          \\\"related\\\": {\\n            \\\"owner_booking_id\\\": \\\"a1ebdd9d-db42-4cd3-a915-0202a034284a\\\"\\n          },\\n          \\\"customer\\\": {\\n            \\\"name\\\": \\\"Marty McFly\\\",\\n            \\\"email\\\": \\\"Marty.McFly@example.com\\\"\\n          }\\n        }' \\\\\\n     https://api.timekit.io/v2/bookings\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nOnly 19 spots left now. Hurry up!\n\nIt's possible for customers to book more than one seat at once, so actually, let's make that 18, because Marty is bringing a friend. This can be indicated with the `seats` option in our request:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example\\n# [POST] /bookings\\ncurl -X POST \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n          \\\"graph\\\": \\\"group_customer\\\",\\n          \\\"action\\\": \\\"create\\\",\\n          \\\"related\\\": {\\n            \\\"owner_booking_id\\\": \\\"a1ebdd9d-db42-4cd3-a915-0202a034284a\\\",\\n            \\\"seats\\\": 2\\n          },\\n          \\\"customer\\\": {\\n            \\\"name\\\": \\\"Marty McFly\\\",\\n            \\\"email\\\": \\\"Marty.McFly@example.com\\\"\\n          }\\n        }' \\\\\\n     https://api.timekit.io/v2/bookings\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nMarty will now have reserved 2 seats out of the 20 available ones.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"2b. Integrating payments for signups\"\n}\n[/block]\nIf your booking flow involves some kind of payment option, you are able to indicate whether a customer has paid using the `group_customer_payment` graph. There are a few things that makes it differ from the standard `group_customer` graph. The first booking state, after creation, is “tentative” and this is when you will want to show your checkout window (e.g. using [Stripe checkout.js](https://stripe.com/docs/checkout)). A seat is locked to the customer while in the tentative state.\n\nHere's how the `group_customer_payment` graph looks:\n\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/f9c0d0e-group_customer_payment_graph.png\",\n        \"group_customer_payment_graph.png\",\n        612,\n        1261,\n        \"#2c7758\"\n      ],\n      \"caption\": \"The `group_customer_payment` graph.\"\n    }\n  ]\n}\n[/block]\nIf you successfully receive payment for the booking, you need to afterwards call the “pay” action on the booking to transition it into its “paid” state. This action takes a `payment_id` attribute so you can store a transaction ID together with the booking for future reference.\n\nIf the customer fails to pay within a timeout limit (default is 5 minutes), the booking will automatically transition into an “unpaid” state and the seat is released for another customer to book.\n\nThis time, the class was free. Next time, though, Marty will have to pay. Let's sign him up using the `group_customer_payment` graph to see how it looks:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example\\n# [POST] /bookings\\ncurl -X POST \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n          \\\"graph\\\": \\\"group_customer_payment\\\",\\n          \\\"action\\\": \\\"create\\\",\\n          \\\"related\\\": {\\n            \\\"owner_booking_id\\\": \\\"a1ebdd9d-db42-4cd3-a915-0202a034284a\\\"\\n          },\\n          \\\"customer\\\": {\\n            \\\"name\\\": \\\"Marty McFly\\\",\\n            \\\"email\\\": \\\"Marty.McFly@example.com\\\"\\n          }\\n        }' \\\\\\n     https://api.timekit.io/v2/bookings\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nTo indicate that Marty has paid, all we need to do is to update the payment state of his booking:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example (replace :payment_id_string)\\n# [PUT] /bookings/9d3fc349-5605-4bbf-a8fd-270fee55c137/pay\\ncurl -X PUT \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n          \\\"pay\\\": {\\n            \\\"payment_id\\\": \\\":payment_id_string\\\"\\n          }\\n        }' \\\\\\n     https://api.timekit.io/v2/bookings/9d3fc349-5605-4bbf-a8fd-270fee55c137/pay\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nYou decide what to send as `payment_id`, but normally this would be something like a transaction ID from Stripe.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Use Stripe?\",\n  \"body\": \"*If you use Stripe, our `group_customer_payment` graph makes it easy to implement payments with Timekit.*\\n\\nWhen you have signed up a customer for a group booking, the booking will be in a `tentative` state. This is where you will show your checkout window (e.g. using checkout.js) and receive the payment. Once the payment is received and processed, you need to call the `/pay` endpoint on the booking in order to indicate the new state. When this is done, the booking will be in a `paid` state.\\n\\n&raquo; [Check out Stripe's Detailed Checkout Guide](https://stripe.com/docs/checkout)\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"3. Cancellations\"\n}\n[/block]\nImagine a situation where Marty messed up his schedule (could you see this happen!?) and double booked himself. He would have to cancel yoga... Fortunately, that's pretty simple using the `cancel_by_customer` action and he can even send a message to Doc:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example\\n# [PUT] /bookings/9d3fc349-5605-4bbf-a8fd-270fee55c137/cancel_by_customer\\ncurl -X PUT \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n          \\\"cancel_by_customer\\\": {\\n            \\\"message\\\": \\\"Double booked. Sorry, Doc!\\\"\\n          }\\n        }' \\\\\\n     https://api.timekit.io/v2/bookings/9d3fc349-5605-4bbf-a8fd-270fee55c137/cancel_by_customer\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nEven worse, Doc might have to cancel too! Then no one would get to yoga that Friday. That's done directly on the owner booking with the `cancel` action:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example\\n# [PUT] /bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a/cancel\\ncurl -X PUT \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n          \\\"cancel\\\": {\\n            \\\"message\\\": \\\"Getting the DeLorean fixed that day. Doc.\\\"\\n          }\\n        }' \\\\\\n     https://api.timekit.io/v2/bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a/cancel\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nMarty, and everyone else who signed up, will receive a notification with Doc's message attached. All is well!\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"4. Manage a group booking\"\n}\n[/block]\nBefore class, Doc needs to know how many yoga mats to bring. When we request the owner booking, we can ask the API to include all related customer bookings. It looks like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example\\n# [GET] /bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a\\ncurl -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     https://api.timekit.io/v2/bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a?include=attributes,related_bookings\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nAnd returns something like:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"data\\\": {\\n    \\\"id\\\": \\\"0dad9c8f-2801-4b6f-b898-7c69063bed0d\\\",\\n    \\\"state\\\": \\\"tentative\\\",\\n    \\\"graph\\\": \\\"group_owner\\\",\\n    \\\"completed\\\": false,\\n    \\\"created_at\\\": \\\"2016-02-11T12:39:45+0100\\\",\\n    \\\"updated_at\\\": \\\"2016-02-11T13:12:01+0100\\\",\\n    \\\"attributes\\\": {\\n      \\\"event_info\\\": {\\n        \\\"start\\\": \\\"2016-09-30T08:00:00+00:00\\\",\\n        \\\"end\\\": \\\"2016-09-30T09:00:00+00:00\\\",\\n        \\\"what\\\": \\\"Doc Brown's Friday Yoga Class\\\",\\n        \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n        \\\"calendar_id\\\": \\\"replace-with-id\\\",\\n        \\\"description\\\": \\\"Please arrive 10 minutes before classes begin\\\"\\n      },\\n      \\\"group_booking\\\": {\\n        \\\"current_seats\\\": 2,\\n        \\\"max_seats\\\": 20\\n      }\\n    },\\n    \\\"related_bookings\\\": [\\n  \\t  {\\n  \\t\\t\\t\\\"id\\\": \\\"9d3fc349-5605-4bbf-a8fd-270fee55c137\\\",\\n        \\\"state\\\": \\\"confirmed\\\",\\n        \\\"graph\\\": \\\"group_customer\\\",\\n        \\\"completed\\\": false,\\n        \\\"created_at\\\": \\\"2016-02-11T12:39:45+0100\\\",\\n        \\\"updated_at\\\": \\\"2016-02-11T13:12:01+0100\\\"\\n  \\t\\t},\\n  \\t\\t{\\n  \\t\\t\\t\\\"id\\\": \\\"63550652-6b21-446c-b125-9a4d02bf6747\\\",\\n        \\\"state\\\": \\\"confirmed\\\",\\n        \\\"graph\\\": \\\"group_customer\\\",\\n        \\\"completed\\\": false,\\n        \\\"created_at\\\": \\\"2016-02-11T12:39:45+0100\\\",\\n        \\\"updated_at\\\": \\\"2016-02-11T13:12:01+0100\\\"\\n  \\t\\t}\\n    ]\\n  }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nBecause each customer who signs up to a group booking has an actual booking (following the `group_customer_graph`), `related_bookings` is a reference to all the customer bookings attached to the group.\n\nGreat scott, you've finished our guide! We hope that group bookings make sense to you and that you are ready to dive in. If not, hit us up on the chat and we'll help you get started.\n\nAlso if you haven't already, we recommend that you read these guides too:\n\n- [1) Setup resources & calendars](doc:guide-connect-and-setup-google-user) \n- [2) Availability search & find time](doc:guide-find-time-book-appointment) \n- [3) Building booking experiences with Timekit](doc:building-booking-experiences-with-timekit)","hidden":false,"isReference":false,"link_external":false,"next":{"description":"","pages":[]},"sync_unique":"","updates":[],"childrenPages":[]}

4) Group & class bookings


**Table of contents:** * [Introduction](#introduction) * [What is a group booking?](#what-is-a-group-booking) * [1. Define availability](#1-define-availability) * [2a. Sign up for a group booking](#2a-sign-up-for-a-group-booking) * [2b. Integrating payments for signups](#2b-integrating-payments-for-signups) * [3. Cancellations](#3-cancellations) * [4. Manage a group booking](#4-manage-a-group-booking) [block:api-header] { "type": "basic", "title": "Introduction" } [/block] Through the `/booking` endpoint you are able to set up groups and classes, so that multiple customers can sign up for the same event. You can use the Timekit API to manage everything from your meetings and sales calls to your webinars and yoga classes. Speaking of! Let's have a look at how you would use Timekit to manage the yoga studio you've always wanted to open: [block:api-header] { "type": "basic", "title": "What is a group booking?" } [/block] Timekit offer many different booking flows, each represented as a graph. When you are working with group bookings, you are interacting with two different graphs: The `group_owner` graph and either the `group_customer` or the `group_customer_payment` graph. The `group_owner` graph is used to reserve a time slot in the owners's calendar and make it available for customers to book as a group. You can think of this as the owners availability. If you are going to offer a yoga class on Friday at 7pm, you simply need to add a booking using the `group_owner` graph. When a group booking is set up, customers can book a seat. This is done using the `group_customer` graph or, if your system involves payments, the `group_customer_payment` graph. Customers can sign up for a group booking until there are no available seats left. [block:api-header] { "type": "basic", "title": "1. Define availability" } [/block] Before customers can sign up to our yoga class, we need to configure our availability as owner. This is done by adding a owner booking using the `group_owner` graph. ## Set up availability For this example Doc Brown (Yes! That Doc Brown) is offering a yoga class with 20 seats, at his yoga studio on Sesame St. Middleburg, FL 32068, USA. It takes place on September 30, 2016 at 9:00 - and you don't want to miss it! Using the `group_owner` graph, we can use the following request to set up the class: [block:code] { "codes": [ { "code": "# Request example (replace :calendar-id)\n# [POST] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"graph\": \"group_owner\",\n \"action\": \"create\",\n \"settings\": {\n \"max_seats\": 20\n },\n \"event\": {\n \"start\": \"2016-09-30T08:00:00+00:00\",\n \"end\": \"2016-09-30T09:00:00+00:00\",\n \"what\": \"Doc Brown's Friday Yoga Class\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \"replace-with-id\",\n \"description\": \"Please arrive 10 minutes before classes begin\"\n }\n }' \\\n https://api.timekit.io/v2/bookings", "language": "curl" } ] } [/block] *Notice that we are using [iso6800](https://en.wikipedia.org/wiki/ISO_8601) standard for the timestamp (this is [configurable](https://dash.readme.io/project/timekit/v2/docs/types--formatting)).* Now, the yoga class will be available for customers to sign up for. Hurry up before it sells out! Optionally, you can specify some basic rules for when customers can sign up to your groups. Doc wants you to cancel at least a day before the class begins, book it no more than 14 days in advance and no later than 2 hours before. We can set it up like this: [block:code] { "codes": [ { "code": "# Request example (replace :calendar-id)\n# [POST] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"graph\": \"group_owner\",\n \"action\": \"create\",\n \"settings\": {\n \"max_seats\": 20,\n \"min_cancel_time\": \"1 day\",\n \"min_booking_time\": \"2 hours\",\n \"max_booking_time\": \"14 days\"\n },\n \"event\": {\n \"start\": \"2016-09-30T08:00:00+00:00\",\n \"end\": \"2016-09-30T09:00:00+00:00\",\n \"what\": \"Doc Brown's Friday Yoga Class\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \"replace-with-id\",\n \"description\": \"Please arrive 10 minutes before classes begin\"\n }\n }' \\\n https://api.timekit.io/v2/bookings", "language": "curl" } ] } [/block] [block:callout] { "type": "info", "title": "Setting up multiple groups at once?", "body": "If you are setting up multiple groups at once, say a yoga class every Friday for the next 10 weeks, you will need to call the `/bookings` endpoint 10 times. We are working on a version of our [`/findtime`](http://developers.timekit.io/docs/findtime) endpoint to allow you to query availability in bulk." } [/block] ## Query availability When customers visit Doc's website, we want them to see all his classes. Technically speaking, we want to list all his group bookings that are still in a `tentative` state - meaning that they are neither completed, nor cancelled. We can use the `/bookings/groups` endpoint to query Doc's availability. That looks like this: [block:code] { "codes": [ { "code": "# Request example\n# [GET] /bookings/search\ncurl -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/bookings/groups", "language": "curl" } ] } [/block] And will return something like this: [block:code] { "codes": [ { "code": "{\n \"data\": [\n {\n \"id\": \"0dad9c8f-2801-4b6f-b898-7c69063bed0d\",\n \"state\": \"tentative\",\n \"graph\": \"group_owner\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\",\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2016-09-30T08:00:00+00:00\",\n \"end\": \"2016-09-30T09:00:00+00:00\",\n \"what\": \"Doc Brown's Friday Yoga Class\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \"replace-with-id\",\n \"description\": \"Please arrive 10 minutes before classes begin\"\n },\n \"group_booking\": {\n \"current_seats\": 0,\n \"max_seats\": 20,\n }\n }\n },\n {\n \"id\": \"a1ebdd9d-db42-4cd3-a915-0202a034284a\",\n \"state\": \"tentative\",\n \"graph\": \"group_owner\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\",\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2016-10-07T08:00:00+00:00\",\n \"end\": \"2016-10-07T09:00:00+00:00\",\n \"what\": \"Doc Brown's Friday Yoga Class\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \"replace-with-id\",\n \"description\": \"Please arrive 10 minutes before classes begin\"\n },\n \"group_booking\": {\n \"current_seats\": 0,\n \"max_seats\": 20,\n }\n }\n }\n ]\n}", "language": "json" } ] } [/block] Looks like no one signed up so far!? Guess there's still time to sign up. Let's do it! You can optionally specify a `start` and `end` query parameter, to only get bookings within a given period of time. [block:callout] { "type": "warning", "title": "Is it safe to expose booking data?", "body": "If you publicly expose information about a group booking (similar to what we do in our Booking.js widget), you should always use the `/bookings/groups` endpoint, as opposed to the regular `/booking` endpoint. This endpoint excludes all sensitive information about the group, such as customer information." } [/block] [block:api-header] { "type": "basic", "title": "2a. Sign up for a group booking" } [/block] It appears that a certain Marty McFly is interesting in joining the yoga class. I'm sure Doc will be pleased to know, so let's sign him up using the `group_customer` graph: [block:code] { "codes": [ { "code": "# Request example\n# [POST] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"graph\": \"group_customer\",\n \"action\": \"create\",\n \"related\": {\n \"owner_booking_id\": \"a1ebdd9d-db42-4cd3-a915-0202a034284a\"\n },\n \"customer\": {\n \"name\": \"Marty McFly\",\n \"email\": \"Marty.McFly@example.com\"\n }\n }' \\\n https://api.timekit.io/v2/bookings", "language": "curl" } ] } [/block] Only 19 spots left now. Hurry up! It's possible for customers to book more than one seat at once, so actually, let's make that 18, because Marty is bringing a friend. This can be indicated with the `seats` option in our request: [block:code] { "codes": [ { "code": "# Request example\n# [POST] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"graph\": \"group_customer\",\n \"action\": \"create\",\n \"related\": {\n \"owner_booking_id\": \"a1ebdd9d-db42-4cd3-a915-0202a034284a\",\n \"seats\": 2\n },\n \"customer\": {\n \"name\": \"Marty McFly\",\n \"email\": \"Marty.McFly@example.com\"\n }\n }' \\\n https://api.timekit.io/v2/bookings", "language": "curl" } ] } [/block] Marty will now have reserved 2 seats out of the 20 available ones. [block:api-header] { "type": "basic", "title": "2b. Integrating payments for signups" } [/block] If your booking flow involves some kind of payment option, you are able to indicate whether a customer has paid using the `group_customer_payment` graph. There are a few things that makes it differ from the standard `group_customer` graph. The first booking state, after creation, is “tentative” and this is when you will want to show your checkout window (e.g. using [Stripe checkout.js](https://stripe.com/docs/checkout)). A seat is locked to the customer while in the tentative state. Here's how the `group_customer_payment` graph looks: [block:image] { "images": [ { "image": [ "https://files.readme.io/f9c0d0e-group_customer_payment_graph.png", "group_customer_payment_graph.png", 612, 1261, "#2c7758" ], "caption": "The `group_customer_payment` graph." } ] } [/block] If you successfully receive payment for the booking, you need to afterwards call the “pay” action on the booking to transition it into its “paid” state. This action takes a `payment_id` attribute so you can store a transaction ID together with the booking for future reference. If the customer fails to pay within a timeout limit (default is 5 minutes), the booking will automatically transition into an “unpaid” state and the seat is released for another customer to book. This time, the class was free. Next time, though, Marty will have to pay. Let's sign him up using the `group_customer_payment` graph to see how it looks: [block:code] { "codes": [ { "code": "# Request example\n# [POST] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"graph\": \"group_customer_payment\",\n \"action\": \"create\",\n \"related\": {\n \"owner_booking_id\": \"a1ebdd9d-db42-4cd3-a915-0202a034284a\"\n },\n \"customer\": {\n \"name\": \"Marty McFly\",\n \"email\": \"Marty.McFly@example.com\"\n }\n }' \\\n https://api.timekit.io/v2/bookings", "language": "curl" } ] } [/block] To indicate that Marty has paid, all we need to do is to update the payment state of his booking: [block:code] { "codes": [ { "code": "# Request example (replace :payment_id_string)\n# [PUT] /bookings/9d3fc349-5605-4bbf-a8fd-270fee55c137/pay\ncurl -X PUT \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"pay\": {\n \"payment_id\": \":payment_id_string\"\n }\n }' \\\n https://api.timekit.io/v2/bookings/9d3fc349-5605-4bbf-a8fd-270fee55c137/pay", "language": "curl" } ] } [/block] You decide what to send as `payment_id`, but normally this would be something like a transaction ID from Stripe. [block:callout] { "type": "info", "title": "Use Stripe?", "body": "*If you use Stripe, our `group_customer_payment` graph makes it easy to implement payments with Timekit.*\n\nWhen you have signed up a customer for a group booking, the booking will be in a `tentative` state. This is where you will show your checkout window (e.g. using checkout.js) and receive the payment. Once the payment is received and processed, you need to call the `/pay` endpoint on the booking in order to indicate the new state. When this is done, the booking will be in a `paid` state.\n\n&raquo; [Check out Stripe's Detailed Checkout Guide](https://stripe.com/docs/checkout)" } [/block] [block:api-header] { "type": "basic", "title": "3. Cancellations" } [/block] Imagine a situation where Marty messed up his schedule (could you see this happen!?) and double booked himself. He would have to cancel yoga... Fortunately, that's pretty simple using the `cancel_by_customer` action and he can even send a message to Doc: [block:code] { "codes": [ { "code": "# Request example\n# [PUT] /bookings/9d3fc349-5605-4bbf-a8fd-270fee55c137/cancel_by_customer\ncurl -X PUT \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"cancel_by_customer\": {\n \"message\": \"Double booked. Sorry, Doc!\"\n }\n }' \\\n https://api.timekit.io/v2/bookings/9d3fc349-5605-4bbf-a8fd-270fee55c137/cancel_by_customer", "language": "curl" } ] } [/block] Even worse, Doc might have to cancel too! Then no one would get to yoga that Friday. That's done directly on the owner booking with the `cancel` action: [block:code] { "codes": [ { "code": "# Request example\n# [PUT] /bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a/cancel\ncurl -X PUT \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"cancel\": {\n \"message\": \"Getting the DeLorean fixed that day. Doc.\"\n }\n }' \\\n https://api.timekit.io/v2/bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a/cancel", "language": "curl" } ] } [/block] Marty, and everyone else who signed up, will receive a notification with Doc's message attached. All is well! [block:api-header] { "type": "basic", "title": "4. Manage a group booking" } [/block] Before class, Doc needs to know how many yoga mats to bring. When we request the owner booking, we can ask the API to include all related customer bookings. It looks like this: [block:code] { "codes": [ { "code": "# Request example\n# [GET] /bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a\ncurl -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a?include=attributes,related_bookings", "language": "curl" } ] } [/block] And returns something like: [block:code] { "codes": [ { "code": "{\n \"data\": {\n \"id\": \"0dad9c8f-2801-4b6f-b898-7c69063bed0d\",\n \"state\": \"tentative\",\n \"graph\": \"group_owner\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\",\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2016-09-30T08:00:00+00:00\",\n \"end\": \"2016-09-30T09:00:00+00:00\",\n \"what\": \"Doc Brown's Friday Yoga Class\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \"replace-with-id\",\n \"description\": \"Please arrive 10 minutes before classes begin\"\n },\n \"group_booking\": {\n \"current_seats\": 2,\n \"max_seats\": 20\n }\n },\n \"related_bookings\": [\n \t {\n \t\t\t\"id\": \"9d3fc349-5605-4bbf-a8fd-270fee55c137\",\n \"state\": \"confirmed\",\n \"graph\": \"group_customer\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\"\n \t\t},\n \t\t{\n \t\t\t\"id\": \"63550652-6b21-446c-b125-9a4d02bf6747\",\n \"state\": \"confirmed\",\n \"graph\": \"group_customer\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\"\n \t\t}\n ]\n }\n}", "language": "json" } ] } [/block] Because each customer who signs up to a group booking has an actual booking (following the `group_customer_graph`), `related_bookings` is a reference to all the customer bookings attached to the group. Great scott, you've finished our guide! We hope that group bookings make sense to you and that you are ready to dive in. If not, hit us up on the chat and we'll help you get started. Also if you haven't already, we recommend that you read these guides too: - [1) Setup resources & calendars](doc:guide-connect-and-setup-google-user) - [2) Availability search & find time](doc:guide-find-time-book-appointment) - [3) Building booking experiences with Timekit](doc:building-booking-experiences-with-timekit)
**Table of contents:** * [Introduction](#introduction) * [What is a group booking?](#what-is-a-group-booking) * [1. Define availability](#1-define-availability) * [2a. Sign up for a group booking](#2a-sign-up-for-a-group-booking) * [2b. Integrating payments for signups](#2b-integrating-payments-for-signups) * [3. Cancellations](#3-cancellations) * [4. Manage a group booking](#4-manage-a-group-booking) [block:api-header] { "type": "basic", "title": "Introduction" } [/block] Through the `/booking` endpoint you are able to set up groups and classes, so that multiple customers can sign up for the same event. You can use the Timekit API to manage everything from your meetings and sales calls to your webinars and yoga classes. Speaking of! Let's have a look at how you would use Timekit to manage the yoga studio you've always wanted to open: [block:api-header] { "type": "basic", "title": "What is a group booking?" } [/block] Timekit offer many different booking flows, each represented as a graph. When you are working with group bookings, you are interacting with two different graphs: The `group_owner` graph and either the `group_customer` or the `group_customer_payment` graph. The `group_owner` graph is used to reserve a time slot in the owners's calendar and make it available for customers to book as a group. You can think of this as the owners availability. If you are going to offer a yoga class on Friday at 7pm, you simply need to add a booking using the `group_owner` graph. When a group booking is set up, customers can book a seat. This is done using the `group_customer` graph or, if your system involves payments, the `group_customer_payment` graph. Customers can sign up for a group booking until there are no available seats left. [block:api-header] { "type": "basic", "title": "1. Define availability" } [/block] Before customers can sign up to our yoga class, we need to configure our availability as owner. This is done by adding a owner booking using the `group_owner` graph. ## Set up availability For this example Doc Brown (Yes! That Doc Brown) is offering a yoga class with 20 seats, at his yoga studio on Sesame St. Middleburg, FL 32068, USA. It takes place on September 30, 2016 at 9:00 - and you don't want to miss it! Using the `group_owner` graph, we can use the following request to set up the class: [block:code] { "codes": [ { "code": "# Request example (replace :calendar-id)\n# [POST] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"graph\": \"group_owner\",\n \"action\": \"create\",\n \"settings\": {\n \"max_seats\": 20\n },\n \"event\": {\n \"start\": \"2016-09-30T08:00:00+00:00\",\n \"end\": \"2016-09-30T09:00:00+00:00\",\n \"what\": \"Doc Brown's Friday Yoga Class\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \"replace-with-id\",\n \"description\": \"Please arrive 10 minutes before classes begin\"\n }\n }' \\\n https://api.timekit.io/v2/bookings", "language": "curl" } ] } [/block] *Notice that we are using [iso6800](https://en.wikipedia.org/wiki/ISO_8601) standard for the timestamp (this is [configurable](https://dash.readme.io/project/timekit/v2/docs/types--formatting)).* Now, the yoga class will be available for customers to sign up for. Hurry up before it sells out! Optionally, you can specify some basic rules for when customers can sign up to your groups. Doc wants you to cancel at least a day before the class begins, book it no more than 14 days in advance and no later than 2 hours before. We can set it up like this: [block:code] { "codes": [ { "code": "# Request example (replace :calendar-id)\n# [POST] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"graph\": \"group_owner\",\n \"action\": \"create\",\n \"settings\": {\n \"max_seats\": 20,\n \"min_cancel_time\": \"1 day\",\n \"min_booking_time\": \"2 hours\",\n \"max_booking_time\": \"14 days\"\n },\n \"event\": {\n \"start\": \"2016-09-30T08:00:00+00:00\",\n \"end\": \"2016-09-30T09:00:00+00:00\",\n \"what\": \"Doc Brown's Friday Yoga Class\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \"replace-with-id\",\n \"description\": \"Please arrive 10 minutes before classes begin\"\n }\n }' \\\n https://api.timekit.io/v2/bookings", "language": "curl" } ] } [/block] [block:callout] { "type": "info", "title": "Setting up multiple groups at once?", "body": "If you are setting up multiple groups at once, say a yoga class every Friday for the next 10 weeks, you will need to call the `/bookings` endpoint 10 times. We are working on a version of our [`/findtime`](http://developers.timekit.io/docs/findtime) endpoint to allow you to query availability in bulk." } [/block] ## Query availability When customers visit Doc's website, we want them to see all his classes. Technically speaking, we want to list all his group bookings that are still in a `tentative` state - meaning that they are neither completed, nor cancelled. We can use the `/bookings/groups` endpoint to query Doc's availability. That looks like this: [block:code] { "codes": [ { "code": "# Request example\n# [GET] /bookings/search\ncurl -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/bookings/groups", "language": "curl" } ] } [/block] And will return something like this: [block:code] { "codes": [ { "code": "{\n \"data\": [\n {\n \"id\": \"0dad9c8f-2801-4b6f-b898-7c69063bed0d\",\n \"state\": \"tentative\",\n \"graph\": \"group_owner\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\",\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2016-09-30T08:00:00+00:00\",\n \"end\": \"2016-09-30T09:00:00+00:00\",\n \"what\": \"Doc Brown's Friday Yoga Class\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \"replace-with-id\",\n \"description\": \"Please arrive 10 minutes before classes begin\"\n },\n \"group_booking\": {\n \"current_seats\": 0,\n \"max_seats\": 20,\n }\n }\n },\n {\n \"id\": \"a1ebdd9d-db42-4cd3-a915-0202a034284a\",\n \"state\": \"tentative\",\n \"graph\": \"group_owner\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\",\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2016-10-07T08:00:00+00:00\",\n \"end\": \"2016-10-07T09:00:00+00:00\",\n \"what\": \"Doc Brown's Friday Yoga Class\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \"replace-with-id\",\n \"description\": \"Please arrive 10 minutes before classes begin\"\n },\n \"group_booking\": {\n \"current_seats\": 0,\n \"max_seats\": 20,\n }\n }\n }\n ]\n}", "language": "json" } ] } [/block] Looks like no one signed up so far!? Guess there's still time to sign up. Let's do it! You can optionally specify a `start` and `end` query parameter, to only get bookings within a given period of time. [block:callout] { "type": "warning", "title": "Is it safe to expose booking data?", "body": "If you publicly expose information about a group booking (similar to what we do in our Booking.js widget), you should always use the `/bookings/groups` endpoint, as opposed to the regular `/booking` endpoint. This endpoint excludes all sensitive information about the group, such as customer information." } [/block] [block:api-header] { "type": "basic", "title": "2a. Sign up for a group booking" } [/block] It appears that a certain Marty McFly is interesting in joining the yoga class. I'm sure Doc will be pleased to know, so let's sign him up using the `group_customer` graph: [block:code] { "codes": [ { "code": "# Request example\n# [POST] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"graph\": \"group_customer\",\n \"action\": \"create\",\n \"related\": {\n \"owner_booking_id\": \"a1ebdd9d-db42-4cd3-a915-0202a034284a\"\n },\n \"customer\": {\n \"name\": \"Marty McFly\",\n \"email\": \"Marty.McFly@example.com\"\n }\n }' \\\n https://api.timekit.io/v2/bookings", "language": "curl" } ] } [/block] Only 19 spots left now. Hurry up! It's possible for customers to book more than one seat at once, so actually, let's make that 18, because Marty is bringing a friend. This can be indicated with the `seats` option in our request: [block:code] { "codes": [ { "code": "# Request example\n# [POST] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"graph\": \"group_customer\",\n \"action\": \"create\",\n \"related\": {\n \"owner_booking_id\": \"a1ebdd9d-db42-4cd3-a915-0202a034284a\",\n \"seats\": 2\n },\n \"customer\": {\n \"name\": \"Marty McFly\",\n \"email\": \"Marty.McFly@example.com\"\n }\n }' \\\n https://api.timekit.io/v2/bookings", "language": "curl" } ] } [/block] Marty will now have reserved 2 seats out of the 20 available ones. [block:api-header] { "type": "basic", "title": "2b. Integrating payments for signups" } [/block] If your booking flow involves some kind of payment option, you are able to indicate whether a customer has paid using the `group_customer_payment` graph. There are a few things that makes it differ from the standard `group_customer` graph. The first booking state, after creation, is “tentative” and this is when you will want to show your checkout window (e.g. using [Stripe checkout.js](https://stripe.com/docs/checkout)). A seat is locked to the customer while in the tentative state. Here's how the `group_customer_payment` graph looks: [block:image] { "images": [ { "image": [ "https://files.readme.io/f9c0d0e-group_customer_payment_graph.png", "group_customer_payment_graph.png", 612, 1261, "#2c7758" ], "caption": "The `group_customer_payment` graph." } ] } [/block] If you successfully receive payment for the booking, you need to afterwards call the “pay” action on the booking to transition it into its “paid” state. This action takes a `payment_id` attribute so you can store a transaction ID together with the booking for future reference. If the customer fails to pay within a timeout limit (default is 5 minutes), the booking will automatically transition into an “unpaid” state and the seat is released for another customer to book. This time, the class was free. Next time, though, Marty will have to pay. Let's sign him up using the `group_customer_payment` graph to see how it looks: [block:code] { "codes": [ { "code": "# Request example\n# [POST] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"graph\": \"group_customer_payment\",\n \"action\": \"create\",\n \"related\": {\n \"owner_booking_id\": \"a1ebdd9d-db42-4cd3-a915-0202a034284a\"\n },\n \"customer\": {\n \"name\": \"Marty McFly\",\n \"email\": \"Marty.McFly@example.com\"\n }\n }' \\\n https://api.timekit.io/v2/bookings", "language": "curl" } ] } [/block] To indicate that Marty has paid, all we need to do is to update the payment state of his booking: [block:code] { "codes": [ { "code": "# Request example (replace :payment_id_string)\n# [PUT] /bookings/9d3fc349-5605-4bbf-a8fd-270fee55c137/pay\ncurl -X PUT \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"pay\": {\n \"payment_id\": \":payment_id_string\"\n }\n }' \\\n https://api.timekit.io/v2/bookings/9d3fc349-5605-4bbf-a8fd-270fee55c137/pay", "language": "curl" } ] } [/block] You decide what to send as `payment_id`, but normally this would be something like a transaction ID from Stripe. [block:callout] { "type": "info", "title": "Use Stripe?", "body": "*If you use Stripe, our `group_customer_payment` graph makes it easy to implement payments with Timekit.*\n\nWhen you have signed up a customer for a group booking, the booking will be in a `tentative` state. This is where you will show your checkout window (e.g. using checkout.js) and receive the payment. Once the payment is received and processed, you need to call the `/pay` endpoint on the booking in order to indicate the new state. When this is done, the booking will be in a `paid` state.\n\n&raquo; [Check out Stripe's Detailed Checkout Guide](https://stripe.com/docs/checkout)" } [/block] [block:api-header] { "type": "basic", "title": "3. Cancellations" } [/block] Imagine a situation where Marty messed up his schedule (could you see this happen!?) and double booked himself. He would have to cancel yoga... Fortunately, that's pretty simple using the `cancel_by_customer` action and he can even send a message to Doc: [block:code] { "codes": [ { "code": "# Request example\n# [PUT] /bookings/9d3fc349-5605-4bbf-a8fd-270fee55c137/cancel_by_customer\ncurl -X PUT \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"cancel_by_customer\": {\n \"message\": \"Double booked. Sorry, Doc!\"\n }\n }' \\\n https://api.timekit.io/v2/bookings/9d3fc349-5605-4bbf-a8fd-270fee55c137/cancel_by_customer", "language": "curl" } ] } [/block] Even worse, Doc might have to cancel too! Then no one would get to yoga that Friday. That's done directly on the owner booking with the `cancel` action: [block:code] { "codes": [ { "code": "# Request example\n# [PUT] /bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a/cancel\ncurl -X PUT \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"cancel\": {\n \"message\": \"Getting the DeLorean fixed that day. Doc.\"\n }\n }' \\\n https://api.timekit.io/v2/bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a/cancel", "language": "curl" } ] } [/block] Marty, and everyone else who signed up, will receive a notification with Doc's message attached. All is well! [block:api-header] { "type": "basic", "title": "4. Manage a group booking" } [/block] Before class, Doc needs to know how many yoga mats to bring. When we request the owner booking, we can ask the API to include all related customer bookings. It looks like this: [block:code] { "codes": [ { "code": "# Request example\n# [GET] /bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a\ncurl -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a?include=attributes,related_bookings", "language": "curl" } ] } [/block] And returns something like: [block:code] { "codes": [ { "code": "{\n \"data\": {\n \"id\": \"0dad9c8f-2801-4b6f-b898-7c69063bed0d\",\n \"state\": \"tentative\",\n \"graph\": \"group_owner\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\",\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2016-09-30T08:00:00+00:00\",\n \"end\": \"2016-09-30T09:00:00+00:00\",\n \"what\": \"Doc Brown's Friday Yoga Class\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \"replace-with-id\",\n \"description\": \"Please arrive 10 minutes before classes begin\"\n },\n \"group_booking\": {\n \"current_seats\": 2,\n \"max_seats\": 20\n }\n },\n \"related_bookings\": [\n \t {\n \t\t\t\"id\": \"9d3fc349-5605-4bbf-a8fd-270fee55c137\",\n \"state\": \"confirmed\",\n \"graph\": \"group_customer\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\"\n \t\t},\n \t\t{\n \t\t\t\"id\": \"63550652-6b21-446c-b125-9a4d02bf6747\",\n \"state\": \"confirmed\",\n \"graph\": \"group_customer\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\"\n \t\t}\n ]\n }\n}", "language": "json" } ] } [/block] Because each customer who signs up to a group booking has an actual booking (following the `group_customer_graph`), `related_bookings` is a reference to all the customer bookings attached to the group. Great scott, you've finished our guide! We hope that group bookings make sense to you and that you are ready to dive in. If not, hit us up on the chat and we'll help you get started. Also if you haven't already, we recommend that you read these guides too: - [1) Setup resources & calendars](doc:guide-connect-and-setup-google-user) - [2) Availability search & find time](doc:guide-find-time-book-appointment) - [3) Building booking experiences with Timekit](doc:building-booking-experiences-with-timekit)
{"_id":"55113a4b9171e82b0089715a","category":"551139dd9171e82b00897159","createdAt":"2015-03-24T10:19:55.179Z","link_url":"","title":"/accounts","updates":[],"parentDoc":null,"type":"get","api":{"settings":"","url":"/accounts","auth":"required","examples":{"codes":[{"language":"curl","code":"curl -X GET \\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n     https://api.timekit.io/v2/accounts"}]},"method":"get","params":[],"results":{"codes":[{"name":"","code":"{\n  \"data\": [\n    {\n      \"provider\": \"google\",\n      \"provider_id\": \"doc.brown@timekit.io\",\n      \"last_sync\": \"2016-09-01 15:51:43\",\n      \"exception\": null,\n      \"error\": null,\n      \"error_at\": null,\n      \"created_at\": \"2016-09-01 15:51:43\",\n      \"updated_at\": \"2016-09-01 15:51:43\",\n    },\n    {\n      \"provider\": \"google\",\n      \"provider_id\": \"marty.mcfly@timekit.io\",\n      \"last_sync\": \"2015-03-17 15:51:43\",\n      \"exception\": null,\n      \"error\": null,\n      \"error_at\": null,\n      \"created_at\": \"2016-09-01 15:51:43\",\n      \"updated_at\": \"2016-09-01 15:51:43\",\n    }\n  ]\n}","language":"json","status":200},{"name":"","code":"Invalid credentials.","language":"text","status":401}]}},"body":"This retrieves a list of the user's connected calendar providers. \n\nAccounts can be synchronized to their provider by calling [[GET] /accounts/sync](doc:accountssync).\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"We currently only support Google accounts, but are adding more providers in the near future\"\n}\n[/block]","excerpt":"","isReference":true,"link_external":false,"__v":3,"order":0,"user":"550ada38cd78a42300ddf508","version":"550bfb5522ccb01700a79469","githubsync":"","hidden":false,"next":{"description":"","pages":[]},"project":"550ada512188a71900453199","slug":"accounts","sync_unique":"","childrenPages":[]}

get/accounts


This retrieves a list of the user's connected calendar providers. Accounts can be synchronized to their provider by calling [[GET] /accounts/sync](doc:accountssync). [block:callout] { "type": "warning", "body": "We currently only support Google accounts, but are adding more providers in the near future" } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



This retrieves a list of the user's connected calendar providers. Accounts can be synchronized to their provider by calling [[GET] /accounts/sync](doc:accountssync). [block:callout] { "type": "warning", "body": "We currently only support Google accounts, but are adding more providers in the near future" } [/block]
{"_id":"55113b5a88e84619004bd4db","api":{"method":"get","params":[{"ref":"","required":false,"type":"string","in":"query","_id":"55e498b4830ec32300e1a34e","default":"","desc":"Url to make the callback to after authentication","name":"callback"}],"results":{"codes":[{"status":301,"language":"text","code":"Redirect to google signup page","name":""},{"name":"","status":400,"language":"json","code":"{\n  \"error\": {\n    \"message\": \"Missing app param\",\n    \"status_code\": 400\n  }\n} "}]},"settings":"","url":"/accounts/google/signup","auth":"never","examples":{"codes":[]}},"parentDoc":null,"project":"550ada512188a71900453199","slug":"accountsgooglesignup","sync_unique":"","body":"This will initiate the Google authentication flow for the current user. A request will result in a redirect to Google's own login browser screen, and upon submit or cancel, will be redirected back the App's registered callback URL (App registration on Timekit is necessary, please get in touch).\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Callback URL\",\n  \"body\": \"If you dont have a callback URL registered in your app settings (or you need to overwrite it), then you can supply the callback as a GET param. Eg. /accounts/google/signup?callback=http://my-api.com/callback\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Timekit App header\",\n  \"body\": \"If you're attempting to visit this URL directly in the browser, you can append a ?Timekit-App=myappname to the URL instead of setting it through the request header\"\n}\n[/block]\nThis endpoint can be used both for sign up (of a new Google account not known to Timekit) or as authentication for a known account (based on email address). This also means that multiple Google accounts can be attached to a single user if needed.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"After signing up a new account, calendars belonging to that accounts must be chosen to be synced afterwards. This is done with the [[PUT] /calendars/:id](doc:calendarsid-2) endpoint.\",\n  \"title\": \"Picking calendars to sync\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Deleting accounts\",\n  \"body\": \"If you want to disconnect Timekit integration with a Google account, it can be done on [this page](https://security.google.com/settings/security/permissions) (logged in with the Google account in question)\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"Read more about the [Google authentication flow here](doc:authentication)\"\n}\n[/block]","link_external":false,"githubsync":"","hidden":false,"title":"/accounts/google/signup","updates":[],"user":"550ada38cd78a42300ddf508","version":"550bfb5522ccb01700a79469","editedParams2":true,"excerpt":"","category":"551139dd9171e82b00897159","createdAt":"2015-03-24T10:24:26.031Z","editedParams":true,"isReference":true,"link_url":"","order":1,"__v":2,"type":"get","childrenPages":[]}

get/accounts/google/signup


Query Params

callback:
string
Url to make the callback to after authentication
This will initiate the Google authentication flow for the current user. A request will result in a redirect to Google's own login browser screen, and upon submit or cancel, will be redirected back the App's registered callback URL (App registration on Timekit is necessary, please get in touch). [block:callout] { "type": "success", "title": "Callback URL", "body": "If you dont have a callback URL registered in your app settings (or you need to overwrite it), then you can supply the callback as a GET param. Eg. /accounts/google/signup?callback=http://my-api.com/callback" } [/block] [block:callout] { "type": "info", "title": "Timekit App header", "body": "If you're attempting to visit this URL directly in the browser, you can append a ?Timekit-App=myappname to the URL instead of setting it through the request header" } [/block] This endpoint can be used both for sign up (of a new Google account not known to Timekit) or as authentication for a known account (based on email address). This also means that multiple Google accounts can be attached to a single user if needed. [block:callout] { "type": "info", "body": "After signing up a new account, calendars belonging to that accounts must be chosen to be synced afterwards. This is done with the [[PUT] /calendars/:id](doc:calendarsid-2) endpoint.", "title": "Picking calendars to sync" } [/block] [block:callout] { "type": "warning", "title": "Deleting accounts", "body": "If you want to disconnect Timekit integration with a Google account, it can be done on [this page](https://security.google.com/settings/security/permissions) (logged in with the Google account in question)" } [/block] [block:callout] { "type": "info", "body": "Read more about the [Google authentication flow here](doc:authentication)" } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Result Format



This will initiate the Google authentication flow for the current user. A request will result in a redirect to Google's own login browser screen, and upon submit or cancel, will be redirected back the App's registered callback URL (App registration on Timekit is necessary, please get in touch). [block:callout] { "type": "success", "title": "Callback URL", "body": "If you dont have a callback URL registered in your app settings (or you need to overwrite it), then you can supply the callback as a GET param. Eg. /accounts/google/signup?callback=http://my-api.com/callback" } [/block] [block:callout] { "type": "info", "title": "Timekit App header", "body": "If you're attempting to visit this URL directly in the browser, you can append a ?Timekit-App=myappname to the URL instead of setting it through the request header" } [/block] This endpoint can be used both for sign up (of a new Google account not known to Timekit) or as authentication for a known account (based on email address). This also means that multiple Google accounts can be attached to a single user if needed. [block:callout] { "type": "info", "body": "After signing up a new account, calendars belonging to that accounts must be chosen to be synced afterwards. This is done with the [[PUT] /calendars/:id](doc:calendarsid-2) endpoint.", "title": "Picking calendars to sync" } [/block] [block:callout] { "type": "warning", "title": "Deleting accounts", "body": "If you want to disconnect Timekit integration with a Google account, it can be done on [this page](https://security.google.com/settings/security/permissions) (logged in with the Google account in question)" } [/block] [block:callout] { "type": "info", "body": "Read more about the [Google authentication flow here](doc:authentication)" } [/block]
{"_id":"55113d740c1a08190077f6be","slug":"accountssync","__v":3,"api":{"results":{"codes":[{"status":200,"language":"json","code":"{\n  \"description\": \"Synced 25 events\",\n  \"count\": 25\n}","name":""},{"name":"","status":400,"language":"json","code":"{}"}]},"settings":"","url":"/accounts/sync","auth":"required","examples":{"codes":[{"language":"curl","code":"curl -X GET \\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n     https://api.timekit.io/v2/accounts/sync"}]},"method":"get","params":[{"required":false,"type":"string","in":"query","_id":"56b4b4ce59d1230d0093a2dd","default":"false","desc":"Set to true, to force a full sync","name":"full_sync","ref":""}]},"body":"Performs an incremental sync of all a user's connected accounts per default. \n\nIf you want to force a full sync, it will delete all Google-connected events on Timekit and then trigger a sync. You can do it by adding `full_sync=true` like this: `/accounts/sync?full_sync=true`. This will fetch events 1 month in the past and 2 months into the future. Although this shouldn't be necessary to do manually, it's a safe way to make sure that all events are up-to-date with Google.","category":"551139dd9171e82b00897159","createdAt":"2015-03-24T10:33:24.315Z","editedParams":true,"next":{"description":"","pages":[]},"sync_unique":"","githubsync":"","hidden":false,"link_url":"","editedParams2":true,"excerpt":"","isReference":true,"order":2,"title":"/accounts/sync","user":"550ada38cd78a42300ddf508","link_external":false,"parentDoc":null,"project":"550ada512188a71900453199","type":"get","updates":[],"version":"550bfb5522ccb01700a79469","childrenPages":[]}

get/accounts/sync


Query Params

full_sync:
stringfalse
Set to true, to force a full sync
Performs an incremental sync of all a user's connected accounts per default. If you want to force a full sync, it will delete all Google-connected events on Timekit and then trigger a sync. You can do it by adding `full_sync=true` like this: `/accounts/sync?full_sync=true`. This will fetch events 1 month in the past and 2 months into the future. Although this shouldn't be necessary to do manually, it's a safe way to make sure that all events are up-to-date with Google.

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



Performs an incremental sync of all a user's connected accounts per default. If you want to force a full sync, it will delete all Google-connected events on Timekit and then trigger a sync. You can do it by adding `full_sync=true` like this: `/accounts/sync?full_sync=true`. This will fetch events 1 month in the past and 2 months into the future. Although this shouldn't be necessary to do manually, it's a safe way to make sure that all events are up-to-date with Google.
{"_id":"551133f9e2990b0d00fb04b8","__v":2,"api":{"auth":"never","examples":{"codes":[{"language":"curl","code":"curl -X POST \\\n     -d '{\n           \"email\": \"doc.brown@timekit.io\",\n           \"password\": \"FluxCapacitator\"\n       }' \\\n  https://api.timekit.io/v2/auth"}]},"method":"post","params":[{"default":"","desc":"Email of the user","name":"email","ref":"","required":false,"type":"string","in":"body","_id":"551133f9e2990b0d00fb04ba"},{"desc":"Password of the user","name":"password","ref":"","required":false,"type":"string","in":"body","_id":"551133f9e2990b0d00fb04b9","default":""}],"results":{"codes":[{"status":200,"language":"json","code":"{\n\t\"data\": {\n    \"id\": \"fca27950-1be8-41e2-951c-a43a61d45d43\",\n\t\t\"first_name\": \"Dr. Emmett\",\n\t\t\"last_name\": \"Brown\",\n\t\t\"name\": \"Dr. Emmett Brown\",\n\t\t\"email\": \"doc.brown@timekit.io\",\n\t\t\"image\": \"http:\\/\\/www.gravatar.com\\/avatar\\/35b00087ea20066e5da95f8359183f04\",\n\t\t\"timezone\": \"America\\/Los_Angeles\",\n\t\t\"api_token\": \"nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW\"\n\t}\n}","name":""},{"status":422,"language":"json","code":"{\t\n  \"errors\": {\n    \"email\": [\n      \"The email field is required.\"\n    ],\n    \"password\": [\n      \"The password field is required.\"\n    ]\n}","name":""},{"status":401,"language":"json","code":"{\n  \"error\": {\n\t\"message\": \"Email and password does not match any user\",\n\t\"status_code\": 401\n}"}]},"settings":"","url":"/auth"},"hidden":false,"sync_unique":"","type":"post","updates":["577ba9ff8d2b4a0e00e20a83"],"createdAt":"2015-03-24T09:52:57.536Z","link_url":"","project":"550ada512188a71900453199","slug":"auth","editedParams":true,"editedParams2":true,"isReference":true,"parentDoc":null,"title":"/auth","body":"This is the only publicly accessible endpoint and is used for authenticating and retrieving an API token for subsequent calls. \n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"Read more about authentication [here](http://developers.timekit.io/v2/docs/authentication)\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Publicly accessible endpoint\",\n  \"body\": \"This endpoint is publicly accessible without authentication and can be used for retrieving an API token in your frontend app if you use Timekit as the sole user/auth provider.\"\n}\n[/block]","category":"55113402a226890d00911640","excerpt":"","githubsync":"","link_external":false,"next":{"description":"","pages":[]},"order":0,"user":"550ada38cd78a42300ddf508","version":"550bfb5522ccb01700a79469","childrenPages":[]}

post/auth


Body Params

email:
string
Email of the user
password:
string
Password of the user
This is the only publicly accessible endpoint and is used for authenticating and retrieving an API token for subsequent calls. [block:callout] { "type": "info", "body": "Read more about authentication [here](http://developers.timekit.io/v2/docs/authentication)" } [/block] [block:callout] { "type": "success", "title": "Publicly accessible endpoint", "body": "This endpoint is publicly accessible without authentication and can be used for retrieving an API token in your frontend app if you use Timekit as the sole user/auth provider." } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



This is the only publicly accessible endpoint and is used for authenticating and retrieving an API token for subsequent calls. [block:callout] { "type": "info", "body": "Read more about authentication [here](http://developers.timekit.io/v2/docs/authentication)" } [/block] [block:callout] { "type": "success", "title": "Publicly accessible endpoint", "body": "This endpoint is publicly accessible without authentication and can be used for retrieving an API token in your frontend app if you use Timekit as the sole user/auth provider." } [/block]
{"_id":"55a6580d51457325000e4d39","version":"550bfb5522ccb01700a79469","body":"You can use this endpoint to create app (registered \"clients\" that access our API) on the Timekit platform.\n\nThe provided app name will automatically be slugged.\n\nSettings are key-value pairs that is coupled together with your app. See the [[PUT] /apps/:slug](doc:appsslug) endpoint\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"Read more about [application context](doc:application-context)\"\n}\n[/block]","githubsync":"","isReference":true,"project":"550ada512188a71900453199","link_url":"","sync_unique":"","user":"550ada38cd78a42300ddf508","api":{"auth":"required","examples":{"codes":[{"language":"curl","code":"curl -X POST \\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n     -d '{\n           \"name\": \"Back to the future\",\n           \"settings\": {\n\t\t\t\t\t \t\t\"name\": \"Back to the future\",\n              \"callback\": \"http://myapp.io/#/googlecallback\",\n              \"from_email\": \"robert.zemeckis@universalpictures.com\",\n              \"from_name\": \"Robert\",\n              \"contact_name\": \"Zemeckis\",\n              \"contact_email\": \"robert.zemeckis@universalpictures.com\"\n\t\t\t\t\t }\n         }' \\\n     https://api.timekit.io/v2/apps","name":""}]},"method":"post","params":[{"type":"string","_id":"55a6580d51457325000e4d3a","default":"","desc":"Name of the app, will automatically be slugged (must be unique)","in":"body","name":"name","ref":"","required":true},{"default":"","desc":"Key-value object with settings","in":"body","name":"settings","ref":"","required":false,"type":"object","_id":"55f8a29d30f2600d00f932c5"}],"results":{"codes":[{"code":"{\n  \"data\": {\n    \"id\": \"MJnllL3rheUYLb0apziz9WH1VXDSuNW3\",\n    \"slug\": \"back-to-the-future\",\n    \"settings\": {\n      \t\"name\": \"Back to the Future\",\n        \"callback\": \"http://myapp.io/#/googlecallback\",\n        \"from_email\": \"robert.zemeckis@universalpictures.com\",\n        \"from_name\": \"Robert\",\n        \"contact_name\": \"Zemeckis\",\n        \"contact_email\": \"robert.zemeckis@universalpictures.com\"\n    }\n  }\n}","name":"","status":201,"language":"json"},{"name":"","status":400,"language":"json","code":"{}"}]},"settings":"","url":"/apps"},"editedParams":true,"editedParams2":true,"hidden":false,"slug":"apps-1","updates":[],"__v":2,"category":"55a65696aaf9cf190011500a","createdAt":"2015-07-15T12:54:37.441Z","order":0,"parentDoc":null,"title":"/apps","type":"post","excerpt":"Create an app","link_external":false,"next":{"pages":[],"description":""},"childrenPages":[]}

post/apps

Create an app

Body Params

name:
required
string
Name of the app, will automatically be slugged (must be unique)
settings:
object
Key-value object with settings
You can use this endpoint to create app (registered "clients" that access our API) on the Timekit platform. The provided app name will automatically be slugged. Settings are key-value pairs that is coupled together with your app. See the [[PUT] /apps/:slug](doc:appsslug) endpoint [block:callout] { "type": "info", "body": "Read more about [application context](doc:application-context)" } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



You can use this endpoint to create app (registered "clients" that access our API) on the Timekit platform. The provided app name will automatically be slugged. Settings are key-value pairs that is coupled together with your app. See the [[PUT] /apps/:slug](doc:appsslug) endpoint [block:callout] { "type": "info", "body": "Read more about [application context](doc:application-context)" } [/block]
{"_id":"55a65727aaf9cf190011500b","version":"550bfb5522ccb01700a79469","body":"List all the apps (registered \"clients\" that access our API) you have created with their corresponding settings\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"Read more about [application context](doc:application-context)\"\n}\n[/block]","createdAt":"2015-07-15T12:50:47.967Z","project":"550ada512188a71900453199","title":"/apps","__v":6,"link_external":false,"link_url":"","order":1,"parentDoc":null,"slug":"apps","sync_unique":"","category":"55a65696aaf9cf190011500a","excerpt":"","githubsync":"","hidden":false,"next":{"description":"","pages":[]},"type":"get","updates":[],"api":{"auth":"required","examples":{"codes":[{"code":"curl -X GET \\\n\t\t -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n     https://api.timekit.io/v2/apps","language":"curl"}]},"method":"get","params":[],"results":{"codes":[{"status":200,"language":"json","code":"{\n\t\"data\":[\n  \t{\n      \"id\": \"0c3aa054-dcba-4e9f-9717-ac855fe6bb4f\",\n      \"slug\": \"back-to-the-future\",\n      \"settings\": {\n        \"name\": \"Back to the Future\",\n        \"callback\": \"http://myapp.io/#/googlecallback\",\n        \"from_email\": \"robert.zemeckis@universalpictures.com\",\n        \"from_name\": \"Robert\",\n        \"contact_name\": \"Zemeckis\",\n        \"contact_email\": \"robert.zemeckis@universalpictures.com\"\n      },\n      \"stripe_plan\": null,\n      \"stripe_purchased_at\": false,\n      \"created_at\": \"1985-12-04 12:00:00\",\n      \"updated_at\": \"2016-09-01 21:17:55\"\n    },\n    {\n      \"id\": \"e2c8ee41-43d6-455d-a595-8b89d9a39c2d\",\n      \"slug\": \"back-to-the-future-2\",\n      \"settings\": {\n        \"name\": \"Back to the Future Part II\",\n        \"callback\": \"http://myotherapp.io/#/googlecallback\",\n        \"from_email\": \"robert.zemeckis@universalpictures.com\",\n        \"from_name\": \"Robert\",\n        \"contact_name\": \"Zemeckis\",\n        \"contact_email\": \"robert.zemeckis@universalpictures.com\"\n      },\n      \"stripe_plan\": null,\n      \"stripe_purchased_at\": false,\n      \"created_at\": \"1989-11-24 12:00:00\",\n      \"updated_at\": \"2016-09-01 21:17:55\"\n    }\n  ]\n}","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/apps"},"isReference":true,"user":"550ada38cd78a42300ddf508","childrenPages":[]}

get/apps


List all the apps (registered "clients" that access our API) you have created with their corresponding settings [block:callout] { "type": "info", "body": "Read more about [application context](doc:application-context)" } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



List all the apps (registered "clients" that access our API) you have created with their corresponding settings [block:callout] { "type": "info", "body": "Read more about [application context](doc:application-context)" } [/block]
{"_id":"55a65b4f80c8a30d00b3260c","excerpt":"Update an app","hidden":false,"link_url":"","next":{"description":"","pages":[]},"api":{"url":"/apps/:slug","auth":"required","examples":{"codes":[{"language":"curl","code":"curl -X PUT \\\n     -H 'Timekit-App: back-to-the-future' \\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n     -d '{\n     \t\t\t \"settings\": {\n             \"name\": \"Back to the Future\",\n             \"callback\": \"http://myapp.io/#/googlecallback\"\n           }\n         }' \\\n     https://api.timekit.io/v2/apps/back-to-the-future","name":""}]},"method":"put","params":[{"type":"string","_id":"55a65b5eaaf9cf190011501c","default":"","desc":"Slug of the app","in":"path","name":"slug","ref":"","required":true},{"default":"","desc":"A key-value object with settings to save/update","in":"body","name":"settings","ref":"","required":true,"type":"object","_id":"55cbd69f4cf2180d00bb1c0d"}],"results":{"codes":[{"status":204,"name":"","code":" ","language":"json"},{"name":"","code":"{}","language":"json","status":400}]},"settings":""},"body":"Update info/settings for a specific app (registered \"clients\" that access our API)\n\nSettings are simply key-value pairs. There's two built-in settings that are used by Timekit:\n- **name**: human readable name for the app\n- **disableEmail**: boolean that disables all booking emails. default: false\n- **callback**: a URL that the user should be redirected to after a [Google authentication](doc:accountsgooglesignup)\n\nYou can create additional settings that you can retrieve yourself afterwards. Consider it a very simple key-value store with no limitations on value types. Since we merge the settings on our end, you only need to post the keys you wish to update.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"Read more about [application context](doc:application-context)\"\n}\n[/block]","category":"55a65696aaf9cf190011500a","editedParams2":true,"title":"/apps/:slug","version":"550bfb5522ccb01700a79469","githubsync":"","user":"550ada38cd78a42300ddf508","createdAt":"2015-07-15T13:08:31.771Z","order":2,"parentDoc":null,"project":"550ada512188a71900453199","slug":"appsslug","sync_unique":"","type":"put","__v":4,"editedParams":true,"isReference":true,"link_external":false,"updates":["5970b131129ac000388ac7b4"],"childrenPages":[]}

put/apps/:slug

Update an app

Path Params

slug:
required
string
Slug of the app

Body Params

settings:
required
object
A key-value object with settings to save/update
Update info/settings for a specific app (registered "clients" that access our API) Settings are simply key-value pairs. There's two built-in settings that are used by Timekit: - **name**: human readable name for the app - **disableEmail**: boolean that disables all booking emails. default: false - **callback**: a URL that the user should be redirected to after a [Google authentication](doc:accountsgooglesignup) You can create additional settings that you can retrieve yourself afterwards. Consider it a very simple key-value store with no limitations on value types. Since we merge the settings on our end, you only need to post the keys you wish to update. [block:callout] { "type": "info", "body": "Read more about [application context](doc:application-context)" } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



Update info/settings for a specific app (registered "clients" that access our API) Settings are simply key-value pairs. There's two built-in settings that are used by Timekit: - **name**: human readable name for the app - **disableEmail**: boolean that disables all booking emails. default: false - **callback**: a URL that the user should be redirected to after a [Google authentication](doc:accountsgooglesignup) You can create additional settings that you can retrieve yourself afterwards. Consider it a very simple key-value store with no limitations on value types. Since we merge the settings on our end, you only need to post the keys you wish to update. [block:callout] { "type": "info", "body": "Read more about [application context](doc:application-context)" } [/block]
{"_id":"5633911462c48a0d00334ef3","updates":[],"user":"550ada38cd78a42300ddf508","version":"550bfb5522ccb01700a79469","body":"You can delete apps that you are the owner of. The endpoint takes a \"slug\" parameter, which is the auto generated URL safe version of the app name (you can get it when [listing apps](doc:apps))\n\nNote that this will not delete related data (resources, calendars etc.)","category":"55a65696aaf9cf190011500a","isReference":true,"slug":"appsslug-1","title":"/apps/:slug","api":{"results":{"codes":[{"status":204,"language":"json","code":"","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/apps/:slug","auth":"required","examples":{"codes":[{"language":"curl","code":"curl -X DELETE \\\n     -H 'Timekit-App: back-to-the-future' \\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n     https://api.timekit.io/v2/apps/back-to-the-future"}]},"method":"delete","params":[{"required":true,"type":"string","_id":"5633911462c48a0d00334ef4","default":"","desc":"The slug of the app you are trying to delete","in":"path","name":"slug","ref":""}]},"editedParams2":true,"githubsync":"","next":{"description":"","pages":[]},"parentDoc":null,"project":"550ada512188a71900453199","sync_unique":"","__v":1,"excerpt":"","link_url":"","order":3,"createdAt":"2015-10-30T15:47:32.578Z","editedParams":true,"hidden":false,"link_external":false,"type":"delete","childrenPages":[]}

delete/apps/:slug


Path Params

slug:
required
string
The slug of the app you are trying to delete
You can delete apps that you are the owner of. The endpoint takes a "slug" parameter, which is the auto generated URL safe version of the app name (you can get it when [listing apps](doc:apps)) Note that this will not delete related data (resources, calendars etc.)

Definition

{{ api_url }}{{ page_api_url }}

Examples



You can delete apps that you are the owner of. The endpoint takes a "slug" parameter, which is the auto generated URL safe version of the app name (you can get it when [listing apps](doc:apps)) Note that this will not delete related data (resources, calendars etc.)
{"_id":"57fb5b498bc8640e00412e7b","category":"56c6d51cfd00bb0d0016dac5","excerpt":"Create booking","githubsync":"","order":0,"type":"post","version":"550bfb5522ccb01700a79469","link_external":false,"link_url":"","next":{"description":"","pages":[]},"parentDoc":null,"project":"550ada512188a71900453199","title":"/bookings","api":{"params":[{"type":"string","name":"graph","_id":"56a62f14ef5b2f0d0040429a","ref":"","in":"body","required":true,"desc":"Name of the flow graph you want to use","default":""},{"desc":"Event details (dependending on the chosen graph!)","default":"","type":"object","name":"event","_id":"56c6d8ad5652c217008e0882","ref":"","in":"body","required":true},{"name":"customer","_id":"56c6d8ad5652c217008e0881","ref":"","in":"body","required":true,"desc":"Customer info (dependending on the chosen graph!)","default":"","type":"object"},{"type":"string","name":"action","_id":"56bb5a54e59a312b00a15bb2","ref":"","in":"body","required":false,"desc":"Optional name of action that should be triggered right after creation","default":""},{"desc":"Include booking attributes such as event_info in the response","default":"","type":"string","name":"includes","_id":"58c06e0571dbd60f007cdf05","ref":"","in":"query","required":false},{"name":"Timekit-App","_id":"58c06e52edbb130f00a58d5d","ref":"","in":"header","required":false,"desc":"","default":"","type":"string"},{"ref":"","in":"body","required":false,"desc":"You can disable the double-bookings check with: { allow_double_bookings: true }","default":"","type":"object","name":"settings","_id":"58e38b8c0eb4bb0f009f51f1"}],"results":{"codes":[{"name":"","code":"{\n  \"data\": {\n    \"id\": \"58190fc6-1ec0-4ebb-b627-7ce6aa9fc703\",\n    \"graph\": \"confirm_decline\",\n    \"state\": \"tentative\",\n    \"completed\": false,\n    \"created_at\": \"2016-02-11T11:58:45+0100\",\n    \"updated_at\": \"2016-02-11T11:58:47+0100\",\n    \"available_actions\": [\n      \"decline\",\n      \"confirm\"\n    ],\n    \"attributes\": {\n      \"event_info\": {\n        \"start\": \"1955-11-12T21:30:00-07:00\",\n        \"end\": \"1955-11-12T22:15:00-07:00\",\n        \"what\": \"Catch the lightning\",\n        \"where\": \"Courthouse, Hill Valley, CA 95420, USA\",\n        \"description\": \"The lightning strikes at 10:04 PM exactly! I need you to be there Doc!\"\n      }\n    },\n    \"calendar\": {\n      \"id\": \"bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2\",\n      \"name\": \"Important encounters with Marty\",\n      \"display_name\": \"Important encounters with Marty\",\n      \"description\": \"Througout time, Marty and I really need to meet in order for the world not to collapse into Biffy cazyness.\",\n      \"foregroundcolor\": \"#000000\",\n      \"backgroundcolor\": \"#FFFFFF\",\n      \"created_at\": \"2016-02-15T13:21:42+0100\",\n      \"updated_at\": \"2016-02-15T13:21:42+0100\"\n    },\n    \"customers\": [\n      {\n        \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n        \"name\": \"Marty McFly\",\n        \"email\": \"marty.mcfly@timekit.io\",\n        \"phone\": \"(916) 555-4385\",\n        \"voip\": \"McFly\",\n        \"timezone\": \"America/Los_Angeles\"\n      }\n    ]\n  }\n}","language":"json","status":200},{"name":"","code":"{}","language":"json","status":400}]},"settings":"","url":"/bookings","auth":"required","examples":{"codes":[{"name":"","language":"json","code":"{\n  \"graph\": \"confirm_decline\",\n  \"action\": \"create\",\n  \"event\": {\n    \"start\": \"1955-11-12T21:30:00-07:00\",\n    \"end\": \"1955-11-12T22:15:00-07:00\",\n    \"what\": \"Catch the lightning\",\n    \"where\": \"Courthouse, Hill Valley, CA 95420, USA\",\n    \"calendar_id\": \"bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2\",\n    \"description\": \"The lightning strikes at 10:04 PM exactly! I need you to be there Doc!\"\n  },\n  \"customer\": {\n    \"name\": \"Marty McFly\",\n    \"email\": \"marty.mcfly@timekit.io\",\n    \"phone\": \"(916) 555-4385\",\n    \"voip\": \"McFly\",\n    \"timezone\": \"America/Los_Angeles\"\n  },\n\t\"settings\": {\n    \"allow_double_bookings\": true\n  }\n}"},{"language":"curl","code":"curl -X POST \\\n  -H 'Timekit-App: back-to-the-future' \\\n  -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n  -d '{\n  \"graph\": \"confirm_decline\",\n  \"action\": \"create\",\n  \"event\": {\n    \"start\": \"1955-11-12T21:30:00-07:00\",\n    \"end\": \"1955-11-12T22:15:00-07:00\",\n    \"what\": \"Catch the lightning\",\n    \"where\": \"Courthouse, Hill Valley, CA 95420, USA\",\n    \"calendar_id\": \"bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2\",\n    \"description\": \"The lightning strikes at 10:04 PM exactly! I need you to be there Doc!\"\n  },\n  \"customer\": {\n    \"name\": \"Marty McFly\",\n    \"email\": \"marty.mcfly@timekit.io\",\n    \"phone\": \"(916) 555-4385\",\n    \"voip\": \"McFly\",\n    \"timezone\": \"America/Los_Angeles\"\n  },\n\t\"settings\": {\n    \"allow_double_bookings\": true\n  }\n}' \\\n  https://api.timekit.io/v2/bookings\n"}]},"method":"post"},"createdAt":"2016-10-10T09:11:37.592Z","slug":"bookings","__v":4,"body":"[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Building booking experiences with Timekit\",\n  \"body\": \"In our guide \\\"Building booking experiences with Timekit\\\", you will learn everything you need to know to build an awesome booking experience on top of Timekit's powerful booking engine.\\n\\n&raquo; [Read the guide](http://developers.timekit.io/docs/building-booking-experiences-with-timekit)\"\n}\n[/block]\nCreate a new booking tied to the current user/resource (usually provider/vendor).\n\nIf you include the `action` key in the request, the specified action will be run automatically. Note that actions usually require input data, like the `create` action in both the `confirm_decline` and `instant` graphs - it's dependent on `event` and `customer` data being passed.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Flow graphs\",\n  \"body\": \"The available actions on a booking is dependent on which \\\"graph\\\" is was created based on - sort of the \\\"blueprint\\\" for the underlying state machine flow.\"\n}\n[/block]","hidden":false,"isReference":true,"sync_unique":"","updates":[],"user":"57c7e8a25754fa1700b121df","childrenPages":[]}

post/bookings

Create booking

Query Params

includes:
string
Include booking attributes such as event_info in the response

Body Params

graph:
required
string
Name of the flow graph you want to use
event:
required
object
Event details (dependending on the chosen graph!)
customer:
required
object
Customer info (dependending on the chosen graph!)
action:
string
Optional name of action that should be triggered right after creation
settings:
object
You can disable the double-bookings check with: { allow_double_bookings: true }

Headers

Timekit-App:
string
[block:callout] { "type": "success", "title": "Building booking experiences with Timekit", "body": "In our guide \"Building booking experiences with Timekit\", you will learn everything you need to know to build an awesome booking experience on top of Timekit's powerful booking engine.\n\n&raquo; [Read the guide](http://developers.timekit.io/docs/building-booking-experiences-with-timekit)" } [/block] Create a new booking tied to the current user/resource (usually provider/vendor). If you include the `action` key in the request, the specified action will be run automatically. Note that actions usually require input data, like the `create` action in both the `confirm_decline` and `instant` graphs - it's dependent on `event` and `customer` data being passed. [block:callout] { "type": "info", "title": "Flow graphs", "body": "The available actions on a booking is dependent on which \"graph\" is was created based on - sort of the \"blueprint\" for the underlying state machine flow." } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



[block:callout] { "type": "success", "title": "Building booking experiences with Timekit", "body": "In our guide \"Building booking experiences with Timekit\", you will learn everything you need to know to build an awesome booking experience on top of Timekit's powerful booking engine.\n\n&raquo; [Read the guide](http://developers.timekit.io/docs/building-booking-experiences-with-timekit)" } [/block] Create a new booking tied to the current user/resource (usually provider/vendor). If you include the `action` key in the request, the specified action will be run automatically. Note that actions usually require input data, like the `create` action in both the `confirm_decline` and `instant` graphs - it's dependent on `event` and `customer` data being passed. [block:callout] { "type": "info", "title": "Flow graphs", "body": "The available actions on a booking is dependent on which \"graph\" is was created based on - sort of the \"blueprint\" for the underlying state machine flow." } [/block]
{"_id":"56a637da72faef21007479fe","title":"/bookings","type":"get","user":"550ada38cd78a42300ddf508","api":{"params":[{"type":"int","name":"limit","_id":"5728593f90a5580e004191bb","ref":"","in":"query","required":false,"desc":"Pagination limit intervals (X means first X is returned)","default":"1000"},{"required":false,"desc":"Which pagination interval to retrieve (set limit for interval size)","default":"1","type":"int","name":"page","_id":"5728593f90a5580e004191ba","ref":"","in":"query"},{"required":false,"type":"string","_id":"5821eb0563e87b25000cbc8b","default":"","desc":"Add 1 of more search criteria to your query. [Learn more](http://developers.timekit.io/v2/docs/search).","in":"query","name":"search","ref":""}],"results":{"codes":[{"name":"","code":"{\n  \"data\": [\n    {\n      \"id\": \"58190fc6-1ec0-4ebb-b627-7ce6aa9fc703\",\n      \"state\": \"confirmed\",\n      \"graph\": \"confirm_decline\",\n      \"completed\": true,\n      \"created_at\": \"2016-02-11T12:39:45+0100\",\n      \"updated_at\": \"2016-02-11T13:12:01+0100\",\n      \"available_actions\": [],\n      \"attributes\": {\n        \"event_info\": {\n          \"start\": \"1955-11-12T21:30:00-07:00\",\n          \"end\": \"1955-11-12T22:15:00-07:00\",\n          \"what\": \"Catch the lightning\",\n          \"where\": \"Courthouse, Hill Valley, CA 95420, USA\",\n          \"description\": \"The lightning strikes at 10:04 PM exactly! I need you to be there Doc!\"\n        }\n      },\n      \"calendar\": {\n        \"id\": \"bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2\",\n        \"name\": \"Important encounters with Marty\",\n        \"display_name\": \"Important encounters with Marty\",\n        \"description\": \"Througout time, Marty and I really need to meet in order for the world not to collapse into Biffy cazyness.\",\n        \"foregroundcolor\": \"#000000\",\n        \"backgroundcolor\": \"#FFFFFF\",\n        \"created_at\": \"2016-02-15T13:21:42+0100\",\n        \"updated_at\": \"2016-02-15T13:21:42+0100\"\n      },\n      \"customers\": [\n        {\n          \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n          \"name\": \"Marty McFly\",\n          \"email\": \"marty.mcfly@timekit.io\",\n          \"phone\": \"(916) 555-4385\",\n          \"voip\": \"McFly\",\n          \"timezone\": \"America/Los_Angeles\"\n        }\n      ]\n    },\n\t  {\n      \"id\": \"f68979ff-27da-4afd-8d0c-847f9340331b\",\n      \"state\": \"tentative\",\n      \"graph\": \"confirm_decline\",\n      \"completed\": false,\n      \"created_at\": \"2016-02-11T12:39:45+0100\",\n      \"updated_at\": \"2016-02-11T13:12:01+0100\",\n      \"available_actions\": [\n      \t\"confirm\",\n        \"decline\"\n      ],\n      \"attributes\": {\n        \"event_info\": {\n          \"start\": \"1955-11-05T09:30:00-07:00\",\n          \"end\": \"1955-11-05T09:45:00-07:00\",\n          \"what\": \"Deliver the Pacard to the auto shop\",\n          \"where\": \"Western Auto Store, Hill Valley, CA 95420, USA\",\n          \"description\": \"The clutch needs tightening\"\n        }\n      },\n      \"calendar\": {\n        \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n        \"name\": \"My personal calendar\",\n        \"display_name\": \"My personal calendar\",\n        \"description\": \"Notes to self, so I don't remember to to them.\",\n        \"foregroundcolor\": \"#25d6be\",\n        \"backgroundcolor\": \"#ea1cb8\",\n        \"created_at\": \"2016-02-15T13:21:42+0100\",\n        \"updated_at\": \"2016-02-15T13:21:42+0100\"\n      },\n      \"customers\": [\n        {\n          \"id\": \"78a4d873-2a68-41c6-bdd4-c0ca5b35efd3\",\n          \"name\": \"Dr. Emmett Brown\",\n          \"email\": \"doc.brown@timekit.io\",\n          \"phone\": \"(916) 555-4385\",\n          \"voip\": \"DocBrown\",\n          \"timezone\": \"America/Los_Angeles\"\n        }\n      ]\n    }\n  ]\n}","language":"json","status":200},{"name":"","code":"{}","language":"json","status":400}]},"settings":"","url":"/bookings","auth":"required","examples":{"codes":[{"code":"GET https://api.timekit.io/v2/bookings?include=attributes,calendar,customers","language":"http"},{"language":"curl","code":"curl -X GET \\\n     -H 'Timekit-App: back-to-the-future' \\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n  https://api.timekit.io/v2/bookings"}]},"method":"get"},"isReference":true,"link_external":false,"project":"550ada512188a71900453199","slug":"bookings-2","sync_unique":"","version":"550bfb5522ccb01700a79469","__v":9,"category":"56c6d51cfd00bb0d0016dac5","excerpt":"","link_url":"","parentDoc":null,"updates":[],"createdAt":"2016-01-25T14:57:30.583Z","editedParams":true,"editedParams2":true,"hidden":false,"order":1,"body":"[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Building booking experiences with Timekit\",\n  \"body\": \"In our guide \\\"Building booking experiences with Timekit\\\", you will learn everything you need to know to build an awesome booking experience on top of Timekit's powerful booking engine.\\n\\n&raquo; [Read the guide](http://developers.timekit.io/docs/building-booking-experiences-with-timekit)\"\n}\n[/block]\nRetrieve all bookings for the current user/resource. \n\nThe keys returned per booking is dependent on the graph and current state.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Dynamic includes\",\n  \"body\": \"In addition to the basic booking data, you can fetch the following booking-related data:\\n- logs\\n- attributes\\n- customers\\n- calendar\\n- event\\n- available_actions\\n\\nExample:\\nhttps://api.timekit.io/v2/bookings?include=logs,attributes,customers,calendar,event\"\n}\n[/block]","githubsync":"","next":{"description":"","pages":[]},"childrenPages":[]}

get/bookings


Query Params

limit:
integer1000
Pagination limit intervals (X means first X is returned)
page:
integer1
Which pagination interval to retrieve (set limit for interval size)
search:
string
Add 1 of more search criteria to your query. [Learn more](http://developers.timekit.io/v2/docs/search).
[block:callout] { "type": "success", "title": "Building booking experiences with Timekit", "body": "In our guide \"Building booking experiences with Timekit\", you will learn everything you need to know to build an awesome booking experience on top of Timekit's powerful booking engine.\n\n&raquo; [Read the guide](http://developers.timekit.io/docs/building-booking-experiences-with-timekit)" } [/block] Retrieve all bookings for the current user/resource. The keys returned per booking is dependent on the graph and current state. [block:callout] { "type": "info", "title": "Dynamic includes", "body": "In addition to the basic booking data, you can fetch the following booking-related data:\n- logs\n- attributes\n- customers\n- calendar\n- event\n- available_actions\n\nExample:\nhttps://api.timekit.io/v2/bookings?include=logs,attributes,customers,calendar,event" } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



[block:callout] { "type": "success", "title": "Building booking experiences with Timekit", "body": "In our guide \"Building booking experiences with Timekit\", you will learn everything you need to know to build an awesome booking experience on top of Timekit's powerful booking engine.\n\n&raquo; [Read the guide](http://developers.timekit.io/docs/building-booking-experiences-with-timekit)" } [/block] Retrieve all bookings for the current user/resource. The keys returned per booking is dependent on the graph and current state. [block:callout] { "type": "info", "title": "Dynamic includes", "body": "In addition to the basic booking data, you can fetch the following booking-related data:\n- logs\n- attributes\n- customers\n- calendar\n- event\n- available_actions\n\nExample:\nhttps://api.timekit.io/v2/bookings?include=logs,attributes,customers,calendar,event" } [/block]
{"_id":"56a62daa2d58cf0d00164c01","createdAt":"2016-01-25T14:14:02.133Z","editedParams":true,"hidden":false,"isReference":true,"link_external":false,"__v":1,"api":{"settings":"","url":"/bookings/:id","auth":"required","examples":{"codes":[{"language":"curl","code":"curl -X GET \\\n\t\t -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n     https://api.timekit.io/v2/bookings/58190fc6-1ec0-4ebb-b627-7ce6aa9fc703"}]},"method":"get","params":[{"name":"id","ref":"","required":true,"type":"string","in":"path","_id":"56a62daa2d58cf0d00164c02","default":"","desc":"The id of the booking"}],"results":{"codes":[{"status":200,"name":"","code":"{\n  \"data\": {\n    \"id\": \"58190fc6-1ec0-4ebb-b627-7ce6aa9fc703\",\n    \"state\": \"confirmed\",\n    \"graph\": \"confirm_decline\",\n    \"completed\": true,\n    \"created_at\": \"2016-02-11T12:39:45+0100\",\n    \"updated_at\": \"2016-02-11T13:12:01+0100\",\n    \"available_actions\": [],\n    \"attributes\": {\n      \"event_info\": {\n        \"start\": \"1955-11-12T21:30:00-07:00\",\n        \"end\": \"1955-11-12T22:15:00-07:00\",\n        \"what\": \"Catch the lightning\",\n        \"where\": \"Courthouse, Hill Valley, CA 95420, USA\",\n        \"description\": \"The lightning strikes at 10:04 PM exactly! I need you to be there Doc!\"\n      }\n    },\n    \"calendar\": {\n      \"id\": \"bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2\",\n      \"name\": \"Important encounters with Marty\",\n      \"display_name\": \"Important encounters with Marty\",\n      \"description\": \"Througout time, Marty and I really need to meet in order for the world not to collapse into Biffy cazyness.\",\n      \"foregroundcolor\": \"#000000\",\n      \"backgroundcolor\": \"#FFFFFF\",\n      \"created_at\": \"2016-02-15T13:21:42+0100\",\n      \"updated_at\": \"2016-02-15T13:21:42+0100\"\n    },\n    \"customers\": [\n      {\n        \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n        \"name\": \"Marty McFly\",\n        \"email\": \"marty.mcfly@timekit.io\",\n        \"phone\": \"(916) 555-4385\",\n        \"voip\": \"McFly\",\n        \"timezone\": \"America/Los_Angeles\"\n      }\n    ]\n  }\n}","language":"json"},{"name":"","code":"{\n  \"error\": \"Resource does not exist\",\n  \"model\": \"Timekit\\Booking\"\n}","language":"json","status":404}]}},"category":"56c6d51cfd00bb0d0016dac5","user":"550ada38cd78a42300ddf508","order":2,"parentDoc":null,"title":"/bookings/:id","project":"550ada512188a71900453199","excerpt":"","githubsync":"","updates":[],"version":"550bfb5522ccb01700a79469","next":{"description":"","pages":[]},"slug":"bookingsid","type":"get","sync_unique":"","body":"[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Building booking experiences with Timekit\",\n  \"body\": \"In our guide \\\"Building booking experiences with Timekit\\\", you will learn everything you need to know to build an awesome booking experience on top of Timekit's powerful booking engine.\\n\\n&raquo; [Read the guide](http://developers.timekit.io/docs/building-booking-experiences-with-timekit)\"\n}\n[/block]\nRetrieve a specific booking.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"In addition to the basic booking data, you can fetch the following booking-related data:\\n- logs\\n- attributes\\n- customers\\n- calendar\\n- event\\n- available_actions\\n\\nExample:\\nhttps://api.timekit.io/v2/bookings?include=logs,attributes,customers,calendar,event\",\n  \"title\": \"Dynamic includes\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Include raw inputs\",\n  \"body\": \"If you want to retrieve all the inputted data you have previously passed to the booking (on creation and update), you can add the dynamic include query param like so: `?include=inputs` to the URL. This can be useful for debugging.\"\n}\n[/block]","editedParams2":true,"link_url":"","childrenPages":[]}

get/bookings/:id


Path Params

id:
required
string
The id of the booking
[block:callout] { "type": "success", "title": "Building booking experiences with Timekit", "body": "In our guide \"Building booking experiences with Timekit\", you will learn everything you need to know to build an awesome booking experience on top of Timekit's powerful booking engine.\n\n&raquo; [Read the guide](http://developers.timekit.io/docs/building-booking-experiences-with-timekit)" } [/block] Retrieve a specific booking. [block:callout] { "type": "info", "body": "In addition to the basic booking data, you can fetch the following booking-related data:\n- logs\n- attributes\n- customers\n- calendar\n- event\n- available_actions\n\nExample:\nhttps://api.timekit.io/v2/bookings?include=logs,attributes,customers,calendar,event", "title": "Dynamic includes" } [/block] [block:callout] { "type": "info", "title": "Include raw inputs", "body": "If you want to retrieve all the inputted data you have previously passed to the booking (on creation and update), you can add the dynamic include query param like so: `?include=inputs` to the URL. This can be useful for debugging." } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



[block:callout] { "type": "success", "title": "Building booking experiences with Timekit", "body": "In our guide \"Building booking experiences with Timekit\", you will learn everything you need to know to build an awesome booking experience on top of Timekit's powerful booking engine.\n\n&raquo; [Read the guide](http://developers.timekit.io/docs/building-booking-experiences-with-timekit)" } [/block] Retrieve a specific booking. [block:callout] { "type": "info", "body": "In addition to the basic booking data, you can fetch the following booking-related data:\n- logs\n- attributes\n- customers\n- calendar\n- event\n- available_actions\n\nExample:\nhttps://api.timekit.io/v2/bookings?include=logs,attributes,customers,calendar,event", "title": "Dynamic includes" } [/block] [block:callout] { "type": "info", "title": "Include raw inputs", "body": "If you want to retrieve all the inputted data you have previously passed to the booking (on creation and update), you can add the dynamic include query param like so: `?include=inputs` to the URL. This can be useful for debugging." } [/block]
{"_id":"56a637812ec8310d007bc1bc","isReference":true,"slug":"bookingsidaction","sync_unique":"","type":"put","user":"550ada38cd78a42300ddf508","excerpt":"Respond to a booking. For the confirm_decline graph, the valid actions are: confirm and decline.","githubsync":"","hidden":false,"order":3,"parentDoc":null,"title":"/bookings/:id/:action","api":{"settings":"","url":"/bookings/:id/:action","auth":"required","examples":{"codes":[{"language":"curl","code":"curl -X PUT \\\n  -H 'Timekit-App: back-to-the-future' \\\n  -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n  https://api.timekit.io/v2/bookings/58190fc6-1ec0-4ebb-b627-7ce6aa9fc703/confirm"}]},"method":"put","params":[{"required":true,"type":"string","in":"path","_id":"56a637812ec8310d007bc1bd","default":"","desc":"The ID of the booking","name":"id","ref":""},{"desc":"Which action to trigger Event details (dependending on the chosen graph!)","name":"action","ref":"","required":true,"type":"string","in":"path","_id":"56bb64bedabd992100b6750d","default":""}],"results":{"codes":[{"code":"{\n  \"data\": {\n    \"id\": \"58190fc6-1ec0-4ebb-b627-7ce6aa9fc703\",\n    \"graph\": \"confirm_decline\",\n    \"state\": \"confirmed\",\n    \"completed\": false,\n    \"created_at\": \"2016-02-11T11:58:45+0100\",\n    \"updated_at\": \"2016-02-11T11:58:47+0100\",\n    \"available_actions\": [\n      \"decline\",\n      \"confirm\"\n    ],\n    \"attributes\": {\n      \"event_info\": {\n        \"start\": \"1955-11-12T21:30:00-07:00\",\n        \"end\": \"1955-11-12T22:15:00-07:00\",\n        \"what\": \"Catch the lightning\",\n        \"where\": \"Courthouse, Hill Valley, CA 95420, USA\",\n        \"description\": \"The lightning strikes at 10:04 PM exactly! I need you to be there Doc!\"\n      }\n    },\n    \"calendar\": {\n      \"id\": \"bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2\",\n      \"name\": \"Important encounters with Marty\",\n      \"display_name\": \"Important encounters with Marty\",\n      \"description\": \"Througout time, Marty and I really need to meet in order for the world not to collapse into Biffy cazyness.\",\n      \"foregroundcolor\": \"#000000\",\n      \"backgroundcolor\": \"#FFFFFF\",\n      \"created_at\": \"2016-02-15T13:21:42+0100\",\n      \"updated_at\": \"2016-02-15T13:21:42+0100\"\n    },\n    \"customers\": [\n      {\n        \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n        \"name\": \"Marty McFly\",\n        \"email\": \"marty.mcfly@timekit.io\",\n        \"phone\": \"(916) 555-4385\",\n        \"voip\": \"McFly\",\n        \"timezone\": \"America/Los_Angeles\"\n      }\n    ]\n  }\n}","language":"json","status":200,"name":""},{"language":"json","status":400,"name":"","code":"{}"}]}},"body":"[block:callout]\n{\n  \"type\": \"success\",\n  \"body\": \"In our guide \\\"Building booking experiences with Timekit\\\", you will learn everything you need to know to build an awesome booking experience on top of Timekit's powerful booking engine.\\n\\n&raquo; [Read the guide](http://developers.timekit.io/docs/building-booking-experiences-with-timekit)\",\n  \"title\": \"Building booking experiences with Timekit\"\n}\n[/block]\nPerform an action on a booking.\n\nPossible actions are a combination of the flow graph the booking is created on and which current state the booking is in. You can get see a map of all states and actions by calling [[GET] /bookings/graphs/:name](doc:bookingsgraphsid).\n\nSome actions can take inputs/settings. For example, in the `confirm_decline` graph, the `decline` action can take a message and be enabled/disabled - please see [Configurable actions](doc:graphs-reference) for an overview.\n\nIf the action you're performing results in a final state where the booking cannot take other actions (e.g. completed, paid, declined etc), the response will have a `completed` key set to `true`.","editedParams":true,"editedParams2":true,"link_external":false,"link_url":"","__v":2,"createdAt":"2016-01-25T14:56:01.362Z","next":{"description":"","pages":[]},"project":"550ada512188a71900453199","updates":[],"version":"550bfb5522ccb01700a79469","category":"56c6d51cfd00bb0d0016dac5","childrenPages":[]}

put/bookings/:id/:action

Respond to a booking. For the confirm_decline graph, the valid actions are: confirm and decline.

Path Params

id:
required
string
The ID of the booking
action:
required
string
Which action to trigger Event details (dependending on the chosen graph!)
[block:callout] { "type": "success", "body": "In our guide \"Building booking experiences with Timekit\", you will learn everything you need to know to build an awesome booking experience on top of Timekit's powerful booking engine.\n\n&raquo; [Read the guide](http://developers.timekit.io/docs/building-booking-experiences-with-timekit)", "title": "Building booking experiences with Timekit" } [/block] Perform an action on a booking. Possible actions are a combination of the flow graph the booking is created on and which current state the booking is in. You can get see a map of all states and actions by calling [[GET] /bookings/graphs/:name](doc:bookingsgraphsid). Some actions can take inputs/settings. For example, in the `confirm_decline` graph, the `decline` action can take a message and be enabled/disabled - please see [Configurable actions](doc:graphs-reference) for an overview. If the action you're performing results in a final state where the booking cannot take other actions (e.g. completed, paid, declined etc), the response will have a `completed` key set to `true`.

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



[block:callout] { "type": "success", "body": "In our guide \"Building booking experiences with Timekit\", you will learn everything you need to know to build an awesome booking experience on top of Timekit's powerful booking engine.\n\n&raquo; [Read the guide](http://developers.timekit.io/docs/building-booking-experiences-with-timekit)", "title": "Building booking experiences with Timekit" } [/block] Perform an action on a booking. Possible actions are a combination of the flow graph the booking is created on and which current state the booking is in. You can get see a map of all states and actions by calling [[GET] /bookings/graphs/:name](doc:bookingsgraphsid). Some actions can take inputs/settings. For example, in the `confirm_decline` graph, the `decline` action can take a message and be enabled/disabled - please see [Configurable actions](doc:graphs-reference) for an overview. If the action you're performing results in a final state where the booking cannot take other actions (e.g. completed, paid, declined etc), the response will have a `completed` key set to `true`.
{"_id":"58203e996256350f00fc6d9a","hidden":false,"next":{"pages":[],"description":""},"parentDoc":null,"slug":"bookingsgroups","sync_unique":"","title":"/bookings/groups","__v":1,"version":"550bfb5522ccb01700a79469","updates":[],"user":"57c7e8a25754fa1700b121df","order":4,"project":"550ada512188a71900453199","type":"get","category":"56c6d51cfd00bb0d0016dac5","excerpt":"Return all available (`tentative`) group bookings","createdAt":"2016-11-07T08:43:05.244Z","githubsync":"","isReference":true,"link_external":false,"link_url":"","api":{"url":"/bookings/groups","auth":"required","examples":{"codes":[{"language":"curl","code":"curl -X GET \\\n     -H 'Timekit-App: back-to-the-future' \\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n     https://api.timekit.io/v2/bookings/groups"}]},"method":"get","params":[{"desc":"Pagination limit intervals (X means first X is returned)","default":"1000","type":"int","name":"limit","_id":"58203e996256350f00fc6d9c","ref":"","in":"query","required":false},{"_id":"58203e996256350f00fc6d9b","ref":"","in":"query","required":false,"desc":"Which pagination interval to retrieve (set limit for interval size)","default":"1","type":"int","name":"page"},{"name":"search","_id":"5821eb4cef9cfd1b005bbaa2","ref":"","in":"query","required":false,"desc":"Add 1 of more search criteria to your query. [Learn more](http://developers.timekit.io/v2/docs/search).","default":"","type":"string"}],"results":{"codes":[{"status":200,"language":"json","code":"{\n  \"data\": [\n    {\n      \"id\": \"0dad9c8f-2801-4b6f-b898-7c69063bed0d\",\n      \"state\": \"tentative\",\n      \"graph\": \"group_owner\",\n      \"completed\": false,\n      \"created_at\": \"2016-02-11T12:39:45+0100\",\n      \"updated_at\": \"2016-02-11T13:12:01+0100\",\n      \"attributes\": {\n        \"group_booking\": {\n          \"max_seats\": 20,\n          \"current_seats\": 0\n        },\n        \"event_info\": {\n          \"start\": \"2016-09-30T08:00:00+00:00\",\n          \"end\": \"2016-09-30T09:00:00+00:00\",\n          \"what\": \"Doc Brown's 1st lecture on flux capacitance\",\n          \"where\": \"Hill Valley High School, CA 95420, USA\",\n          \"calendar_id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n          \"description\": \"Please arrive 10 minutes before the lecture begins\"\n        }\n      }\n    },\n    {\n      \"id\": \"a1ebdd9d-db42-4cd3-a915-0202a034284a\",\n      \"state\": \"tentative\",\n      \"graph\": \"group_owner\",\n      \"completed\": false,\n      \"created_at\": \"2016-02-11T12:39:45+0100\",\n      \"updated_at\": \"2016-02-11T13:12:01+0100\",\n      \"attributes\": {\n        \"group_booking\": {\n          \"max_seats\": 20,\n          \"current_seats\": 0\n        },\n        \"event_info\": {\n          \"start\": \"2016-10-06T08:00:00+00:00\",\n          \"end\": \"2016-10-06T09:00:00+00:00\",\n          \"what\": \"Doc Brown's 2nd lecture on flux capacitance\",\n          \"where\": \"Hill Valley High School, CA 95420, USA\",\n          \"calendar_id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n          \"description\": \"Please arrive 10 minutes before the lecture begins\"\n        }\n      }\n    }\n  ]\n}","name":""},{"code":"{}","name":"","status":400,"language":"json"}]},"settings":""},"body":"When you want to publicly list all available group bookings for customers to sign up for, you should use this endpoint. It only includes information about the owner event itself, and doesn't include sensitive information about customers etc.\n\nThis endpoint it also the one we use in [Booking.js](https://github.com/timekit-io/booking-js) to list available group bookings.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Dynamic includes\",\n  \"body\": \"For security reasons, you can't dynamically include related resources on this endpoint, like with the regular `/bookings` endpoints.\"\n}\n[/block]","childrenPages":[]}

get/bookings/groups

Return all available (`tentative`) group bookings

Query Params

limit:
integer1000
Pagination limit intervals (X means first X is returned)
page:
integer1
Which pagination interval to retrieve (set limit for interval size)
search:
string
Add 1 of more search criteria to your query. [Learn more](http://developers.timekit.io/v2/docs/search).
When you want to publicly list all available group bookings for customers to sign up for, you should use this endpoint. It only includes information about the owner event itself, and doesn't include sensitive information about customers etc. This endpoint it also the one we use in [Booking.js](https://github.com/timekit-io/booking-js) to list available group bookings. [block:callout] { "type": "warning", "title": "Dynamic includes", "body": "For security reasons, you can't dynamically include related resources on this endpoint, like with the regular `/bookings` endpoints." } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



When you want to publicly list all available group bookings for customers to sign up for, you should use this endpoint. It only includes information about the owner event itself, and doesn't include sensitive information about customers etc. This endpoint it also the one we use in [Booking.js](https://github.com/timekit-io/booking-js) to list available group bookings. [block:callout] { "type": "warning", "title": "Dynamic includes", "body": "For security reasons, you can't dynamically include related resources on this endpoint, like with the regular `/bookings` endpoints." } [/block]
{"_id":"5820500f6256350f00fc6da8","parentDoc":null,"project":"550ada512188a71900453199","title":"/bookings/groups/:id","createdAt":"2016-11-07T09:57:35.140Z","githubsync":"","isReference":true,"user":"57c7e8a25754fa1700b121df","link_url":"","order":5,"slug":"bookingsgroupsid","type":"get","version":"550bfb5522ccb01700a79469","category":"56c6d51cfd00bb0d0016dac5","excerpt":"","api":{"method":"get","params":[],"results":{"codes":[{"language":"json","code":"{\n  \"data\": {\n    \"id\": \"0dad9c8f-2801-4b6f-b898-7c69063bed0d\",\n    \"state\": \"tentative\",\n    \"graph\": \"group_owner\",\n    \"completed\": false,\n    \"created_at\": \"2016-02-11T12:39:45+0100\",\n    \"updated_at\": \"2016-02-11T13:12:01+0100\",\n    \"attributes\": {\n        \"group_booking\": {\n          \"max_seats\": 20,\n          \"current_seats\": 0\n        },\n        \"event_info\": {\n          \"start\": \"2016-09-30T08:00:00+00:00\",\n          \"end\": \"2016-09-30T09:00:00+00:00\",\n          \"what\": \"Doc Brown's 1st lecture on flux capacitance\",\n          \"where\": \"Hill Valley High School, CA 95420, USA\",\n          \"calendar_id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n          \"description\": \"Please arrive 10 minutes before the lecture begins\"\n        }\n      }\n  }\n}","name":"","status":200},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/bookings/groups/:id","auth":"required","examples":{"codes":[{"language":"curl","code":"curl -X GET \\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n     https://api.timekit.io/v2/bookings/groups/0dad9c8f-2801-4b6f-b898-7c69063bed0d"}]}},"body":"When you want to publicly list information about a group bookings, you should use this endpoint. It only includes information about the owner event itself, and doesn't include sensitive information about customers etc.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"For security reasons, you can't dynamically include related resources on this endpoint, like with the regular `/bookings` endpoints.\",\n  \"title\": \"Dynamic includes\"\n}\n[/block]","hidden":false,"link_external":false,"next":{"pages":[],"description":""},"sync_unique":"","__v":0,"updates":[],"childrenPages":[]}

get/bookings/groups/:id


When you want to publicly list information about a group bookings, you should use this endpoint. It only includes information about the owner event itself, and doesn't include sensitive information about customers etc. [block:callout] { "type": "warning", "body": "For security reasons, you can't dynamically include related resources on this endpoint, like with the regular `/bookings` endpoints.", "title": "Dynamic includes" } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



When you want to publicly list information about a group bookings, you should use this endpoint. It only includes information about the owner event itself, and doesn't include sensitive information about customers etc. [block:callout] { "type": "warning", "body": "For security reasons, you can't dynamically include related resources on this endpoint, like with the regular `/bookings` endpoints.", "title": "Dynamic includes" } [/block]
{"_id":"5821e7b2cdcb6d0f0027ca2c","order":6,"project":"550ada512188a71900453199","slug":"search","title":"Search","body":"On every endpoint that returns a list og bookings, you can add a `search` query parameter. Search uses the following format: `?search=attribute:value;attribute:value`.\n\nLet's look at a few examples:\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Ex. 1: Search based on graph\"\n}\n[/block]\nLet's say we want to filter all our bookings based on their graph. Using the `search` query parameter, we can send the following request:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# [GET] /bookings\\ncurl -X POST \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     https://api.timekit.io/v2/bookings?search=graph:confirm_decline\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nWhich would return all bookings using the `confirm_decline` graph:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"data\\\": [\\n    {\\n      \\\"id\\\": \\\"f68979ff-27da-4afd-8d0c-847f9340331b\\\",\\n      \\\"state\\\": \\\"declined\\\",\\n      \\\"graph\\\": \\\"confirm_decline\\\",\\n      \\\"completed\\\": true,\\n      \\\"created_at\\\": \\\"2016-02-11T12:39:45+0100\\\",\\n      \\\"updated_at\\\": \\\"2016-02-11T13:12:01+0100\\\",\\n      \\\"available_actions\\\": [],\\n      \\\"attributes\\\": {\\n        \\\"event_info\\\": {\\n          \\\"start\\\": \\\"2015-01-01T09:00:00+0100\\\",\\n          \\\"end\\\": \\\"2015-01-01T14:00:00+0100\\\",\\n          \\\"what\\\": \\\"Mens haircut\\\",\\n          \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n          \\\"description\\\": \\\"Please arrive 10 minutes before you time begin\\\"\\n        }\\n      },\\n      \\\"calendar\\\": {\\n        \\\"id\\\": \\\"c91c5d04-2a57-46c0-ab35-e489dadf132e\\\",\\n        \\\"name\\\": \\\"My calendar\\\",\\n        \\\"display_name\\\": \\\"My calendar\\\",\\n        \\\"description\\\": \\\"Ut adipisci non autem cum ut id.\\\",\\n        \\\"foregroundcolor\\\": \\\"#25d6be\\\",\\n        \\\"backgroundcolor\\\": \\\"#ea1cb8\\\",\\n        \\\"created_at\\\": \\\"2016-02-15T13:21:42+0100\\\",\\n        \\\"updated_at\\\": \\\"2016-02-15T13:21:42+0100\\\"\\n      },\\n      \\\"customers\\\": [\\n        {\\n          \\\"id\\\": \\\"a728e860-99c7-4009-8843-7d9ac5d7f53f\\\",\\n          \\\"name\\\": \\\"Marty McFly\\\",\\n          \\\"email\\\": \\\"marty.mcfly@timekit.io\\\",\\n          \\\"phone\\\": \\\"1-591-001-5403\\\",\\n          \\\"voip\\\": \\\"McFly\\\",\\n          \\\"timezone\\\": \\\"America/Los_Angeles\\\"\\n        }\\n      ]\\n    },\\n    {\\n      \\\"id\\\": \\\"f68979ff-27da-4afd-8d0c-847f9340331b\\\",\\n      \\\"state\\\": \\\"tentative\\\",\\n      \\\"graph\\\": \\\"confirm_decline\\\",\\n      \\\"completed\\\": false,\\n      \\\"created_at\\\": \\\"2016-02-11T12:39:45+0100\\\",\\n      \\\"updated_at\\\": \\\"2016-02-11T13:12:01+0100\\\",\\n      \\\"available_actions\\\": [\\n        \\\"confirm\\\",\\n        \\\"decline\\\"\\n      ],\\n      \\\"attributes\\\": {\\n        \\\"event_info\\\": {\\n          \\\"start\\\": \\\"2015-01-01T09:00:00+0100\\\",\\n          \\\"end\\\": \\\"2015-01-01T14:00:00+0100\\\",\\n          \\\"what\\\": \\\"Mens haircut\\\",\\n          \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n          \\\"description\\\": \\\"Please arrive 10 minutes before you time begin\\\"\\n        }\\n      },\\n      \\\"calendar\\\": {\\n        \\\"id\\\": \\\"c91c5d04-2a57-46c0-ab35-e489dadf132e\\\",\\n        \\\"name\\\": \\\"My calendar\\\",\\n        \\\"display_name\\\": \\\"My calendar\\\",\\n        \\\"description\\\": \\\"Ut adipisci non autem cum ut id.\\\",\\n        \\\"foregroundcolor\\\": \\\"#25d6be\\\",\\n        \\\"backgroundcolor\\\": \\\"#ea1cb8\\\",\\n        \\\"created_at\\\": \\\"2016-02-15T13:21:42+0100\\\",\\n        \\\"updated_at\\\": \\\"2016-02-15T13:21:42+0100\\\"\\n      },\\n      \\\"customers\\\": [\\n        {\\n          \\\"id\\\": \\\"a728e860-99c7-4009-8843-7d9ac5d7f53f\\\",\\n          \\\"name\\\": \\\"Marty McFly\\\",\\n          \\\"email\\\": \\\"marty.mcfly@timekit.io\\\",\\n          \\\"phone\\\": \\\"1-591-001-5403\\\",\\n          \\\"voip\\\": \\\"McFly\\\",\\n          \\\"timezone\\\": \\\"America/Los_Angeles\\\"\\n        }\\n      ]\\n    }\\n  ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Ex. 2: Search based on graph and state\"\n}\n[/block]\nYou can add multiple criteria to a search, by separating each criteria with a semicolon (`;`). So if we want to filter based on graph _and_ state, we can send the following request:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# [GET] /bookings\\ncurl -X POST \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:FluxCapacitator \\\\\\n     https://api.timekit.io/v2/bookings?search=graph:confirm_decline;state:tentative\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nWhich would return all bookings using the `confirm_decline` graph that are in a `tentative` state:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"data\\\": [\\n    {\\n      \\\"id\\\": \\\"f68979ff-27da-4afd-8d0c-847f9340331b\\\",\\n      \\\"state\\\": \\\"tentative\\\",\\n      \\\"graph\\\": \\\"confirm_decline\\\",\\n      \\\"completed\\\": false,\\n      \\\"created_at\\\": \\\"2016-02-11T12:39:45+0100\\\",\\n      \\\"updated_at\\\": \\\"2016-02-11T13:12:01+0100\\\",\\n      \\\"available_actions\\\": [\\n        \\\"confirm\\\",\\n        \\\"decline\\\"\\n      ],\\n      \\\"attributes\\\": {\\n        \\\"event_info\\\": {\\n          \\\"start\\\": \\\"2015-01-01T09:00:00+0100\\\",\\n          \\\"end\\\": \\\"2015-01-01T14:00:00+0100\\\",\\n          \\\"what\\\": \\\"Mens haircut\\\",\\n          \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n          \\\"description\\\": \\\"Please arrive 10 minutes before you time begin\\\"\\n        }\\n      },\\n      \\\"calendar\\\": {\\n        \\\"id\\\": \\\"c91c5d04-2a57-46c0-ab35-e489dadf132e\\\",\\n        \\\"name\\\": \\\"My calendar\\\",\\n        \\\"display_name\\\": \\\"My calendar\\\",\\n        \\\"description\\\": \\\"Ut adipisci non autem cum ut id.\\\",\\n        \\\"foregroundcolor\\\": \\\"#25d6be\\\",\\n        \\\"backgroundcolor\\\": \\\"#ea1cb8\\\",\\n        \\\"created_at\\\": \\\"2016-02-15T13:21:42+0100\\\",\\n        \\\"updated_at\\\": \\\"2016-02-15T13:21:42+0100\\\"\\n      },\\n      \\\"customers\\\": [\\n        {\\n          \\\"id\\\": \\\"a728e860-99c7-4009-8843-7d9ac5d7f53f\\\",\\n          \\\"name\\\": \\\"Marty McFly\\\",\\n          \\\"email\\\": \\\"marty.mcfly@timekit.io\\\",\\n          \\\"phone\\\": \\\"1-591-001-5403\\\",\\n          \\\"voip\\\": \\\"McFly\\\",\\n          \\\"timezone\\\": \\\"America/Los_Angeles\\\"\\n        }\\n      ]\\n    }\\n  ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]","hidden":false,"githubsync":"","sync_unique":"","user":"57c7e8a25754fa1700b121df","api":{"url":"","results":{"codes":[{"status":200,"language":"json","code":"{}","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","auth":"required","params":[]},"createdAt":"2016-11-08T14:56:50.828Z","isReference":true,"next":{"pages":[],"description":""},"parentDoc":null,"type":"basic","version":"550bfb5522ccb01700a79469","__v":0,"category":"56c6d51cfd00bb0d0016dac5","link_external":false,"link_url":"","updates":[],"excerpt":"Search in bookings","childrenPages":[]}

Search

Search in bookings

On every endpoint that returns a list og bookings, you can add a `search` query parameter. Search uses the following format: `?search=attribute:value;attribute:value`. Let's look at a few examples: [block:api-header] { "type": "basic", "title": "Ex. 1: Search based on graph" } [/block] Let's say we want to filter all our bookings based on their graph. Using the `search` query parameter, we can send the following request: [block:code] { "codes": [ { "code": "# [GET] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/bookings?search=graph:confirm_decline", "language": "curl" } ] } [/block] Which would return all bookings using the `confirm_decline` graph: [block:code] { "codes": [ { "code": "{\n \"data\": [\n {\n \"id\": \"f68979ff-27da-4afd-8d0c-847f9340331b\",\n \"state\": \"declined\",\n \"graph\": \"confirm_decline\",\n \"completed\": true,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\",\n \"available_actions\": [],\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2015-01-01T09:00:00+0100\",\n \"end\": \"2015-01-01T14:00:00+0100\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n }\n },\n \"calendar\": {\n \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n \"name\": \"My calendar\",\n \"display_name\": \"My calendar\",\n \"description\": \"Ut adipisci non autem cum ut id.\",\n \"foregroundcolor\": \"#25d6be\",\n \"backgroundcolor\": \"#ea1cb8\",\n \"created_at\": \"2016-02-15T13:21:42+0100\",\n \"updated_at\": \"2016-02-15T13:21:42+0100\"\n },\n \"customers\": [\n {\n \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n ]\n },\n {\n \"id\": \"f68979ff-27da-4afd-8d0c-847f9340331b\",\n \"state\": \"tentative\",\n \"graph\": \"confirm_decline\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\",\n \"available_actions\": [\n \"confirm\",\n \"decline\"\n ],\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2015-01-01T09:00:00+0100\",\n \"end\": \"2015-01-01T14:00:00+0100\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n }\n },\n \"calendar\": {\n \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n \"name\": \"My calendar\",\n \"display_name\": \"My calendar\",\n \"description\": \"Ut adipisci non autem cum ut id.\",\n \"foregroundcolor\": \"#25d6be\",\n \"backgroundcolor\": \"#ea1cb8\",\n \"created_at\": \"2016-02-15T13:21:42+0100\",\n \"updated_at\": \"2016-02-15T13:21:42+0100\"\n },\n \"customers\": [\n {\n \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n ]\n }\n ]\n}", "language": "json" } ] } [/block] [block:api-header] { "type": "basic", "title": "Ex. 2: Search based on graph and state" } [/block] You can add multiple criteria to a search, by separating each criteria with a semicolon (`;`). So if we want to filter based on graph _and_ state, we can send the following request: [block:code] { "codes": [ { "code": "# [GET] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:FluxCapacitator \\\n https://api.timekit.io/v2/bookings?search=graph:confirm_decline;state:tentative", "language": "curl" } ] } [/block] Which would return all bookings using the `confirm_decline` graph that are in a `tentative` state: [block:code] { "codes": [ { "code": "{\n \"data\": [\n {\n \"id\": \"f68979ff-27da-4afd-8d0c-847f9340331b\",\n \"state\": \"tentative\",\n \"graph\": \"confirm_decline\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\",\n \"available_actions\": [\n \"confirm\",\n \"decline\"\n ],\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2015-01-01T09:00:00+0100\",\n \"end\": \"2015-01-01T14:00:00+0100\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n }\n },\n \"calendar\": {\n \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n \"name\": \"My calendar\",\n \"display_name\": \"My calendar\",\n \"description\": \"Ut adipisci non autem cum ut id.\",\n \"foregroundcolor\": \"#25d6be\",\n \"backgroundcolor\": \"#ea1cb8\",\n \"created_at\": \"2016-02-15T13:21:42+0100\",\n \"updated_at\": \"2016-02-15T13:21:42+0100\"\n },\n \"customers\": [\n {\n \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n ]\n }\n ]\n}", "language": "json" } ] } [/block]
On every endpoint that returns a list og bookings, you can add a `search` query parameter. Search uses the following format: `?search=attribute:value;attribute:value`. Let's look at a few examples: [block:api-header] { "type": "basic", "title": "Ex. 1: Search based on graph" } [/block] Let's say we want to filter all our bookings based on their graph. Using the `search` query parameter, we can send the following request: [block:code] { "codes": [ { "code": "# [GET] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n https://api.timekit.io/v2/bookings?search=graph:confirm_decline", "language": "curl" } ] } [/block] Which would return all bookings using the `confirm_decline` graph: [block:code] { "codes": [ { "code": "{\n \"data\": [\n {\n \"id\": \"f68979ff-27da-4afd-8d0c-847f9340331b\",\n \"state\": \"declined\",\n \"graph\": \"confirm_decline\",\n \"completed\": true,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\",\n \"available_actions\": [],\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2015-01-01T09:00:00+0100\",\n \"end\": \"2015-01-01T14:00:00+0100\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n }\n },\n \"calendar\": {\n \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n \"name\": \"My calendar\",\n \"display_name\": \"My calendar\",\n \"description\": \"Ut adipisci non autem cum ut id.\",\n \"foregroundcolor\": \"#25d6be\",\n \"backgroundcolor\": \"#ea1cb8\",\n \"created_at\": \"2016-02-15T13:21:42+0100\",\n \"updated_at\": \"2016-02-15T13:21:42+0100\"\n },\n \"customers\": [\n {\n \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n ]\n },\n {\n \"id\": \"f68979ff-27da-4afd-8d0c-847f9340331b\",\n \"state\": \"tentative\",\n \"graph\": \"confirm_decline\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\",\n \"available_actions\": [\n \"confirm\",\n \"decline\"\n ],\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2015-01-01T09:00:00+0100\",\n \"end\": \"2015-01-01T14:00:00+0100\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n }\n },\n \"calendar\": {\n \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n \"name\": \"My calendar\",\n \"display_name\": \"My calendar\",\n \"description\": \"Ut adipisci non autem cum ut id.\",\n \"foregroundcolor\": \"#25d6be\",\n \"backgroundcolor\": \"#ea1cb8\",\n \"created_at\": \"2016-02-15T13:21:42+0100\",\n \"updated_at\": \"2016-02-15T13:21:42+0100\"\n },\n \"customers\": [\n {\n \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n ]\n }\n ]\n}", "language": "json" } ] } [/block] [block:api-header] { "type": "basic", "title": "Ex. 2: Search based on graph and state" } [/block] You can add multiple criteria to a search, by separating each criteria with a semicolon (`;`). So if we want to filter based on graph _and_ state, we can send the following request: [block:code] { "codes": [ { "code": "# [GET] /bookings\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:FluxCapacitator \\\n https://api.timekit.io/v2/bookings?search=graph:confirm_decline;state:tentative", "language": "curl" } ] } [/block] Which would return all bookings using the `confirm_decline` graph that are in a `tentative` state: [block:code] { "codes": [ { "code": "{\n \"data\": [\n {\n \"id\": \"f68979ff-27da-4afd-8d0c-847f9340331b\",\n \"state\": \"tentative\",\n \"graph\": \"confirm_decline\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T12:39:45+0100\",\n \"updated_at\": \"2016-02-11T13:12:01+0100\",\n \"available_actions\": [\n \"confirm\",\n \"decline\"\n ],\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2015-01-01T09:00:00+0100\",\n \"end\": \"2015-01-01T14:00:00+0100\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n }\n },\n \"calendar\": {\n \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n \"name\": \"My calendar\",\n \"display_name\": \"My calendar\",\n \"description\": \"Ut adipisci non autem cum ut id.\",\n \"foregroundcolor\": \"#25d6be\",\n \"backgroundcolor\": \"#ea1cb8\",\n \"created_at\": \"2016-02-15T13:21:42+0100\",\n \"updated_at\": \"2016-02-15T13:21:42+0100\"\n },\n \"customers\": [\n {\n \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n ]\n }\n ]\n}", "language": "json" } ] } [/block]
{"_id":"56c6df85b935671700ff02aa","parentDoc":null,"project":"550ada512188a71900453199","slug":"graphs-reference","sync_unique":"","user":"550bf7b2eb24860d00e6a33b","hidden":false,"link_external":false,"body":"By default, emails get sent out to owners and customers when bookings are created and move from state to state. Some emails take parameters, like a message, and you can choose to disable them if you'd like to handle communication yourself (e.g. with the help of [webhooks](doc:webhooks)).\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Enabled by default\",\n  \"body\": \"All emails are enabled by default and you have to manually disable them if you don't want to Timekit to send out any emails at all.\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Disabling emails\"\n}\n[/block]\nIn addition to taking event/customer data and creating calendar events, the `instant` graph also sends out emails and can trigger a webhook.\n\nYou can see all available actions/transitions [here](doc:bookingsgraphsid) and below is a short list of how they can be configured (as JSON body data in your request): \n\n## Graph: instant\n\nBookings created using the \"instant\" graph only send out emails when the booking is created; one email for the owner and one for the customer. \n\nYou can disable them by passing the following in the POST body when creating the bookings:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// Send email to the owner (enabled by default)\\n\\\"notify_owner_by_email\\\": {\\n  \\\"enabled\\\": false\\n}\\n\\n// Send email to the customer (enabled by default)\\n\\\"notify_customer_by_email\\\": {\\n  \\\"enabled\\\": false\\n}\\n\\n// Send email to customer if the booking get cancelled (enabled by default)\\n\\\"notify_customer_cancelled_by_email\\\": {\\n  \\\"enabled\\\": false\\n}\\n\\n// Send email to owner if the booking get cancelled (enabled by default)\\n\\\"notify_owner_cancelled_by_email\\\": {\\n  \\\"enabled\\\": false\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n## Graph: confirm_decline\n\nBookings created using the \"confirm_decline\" graph send out email an email to the owner when the booking is created, but also notifies the customer when the booking is either accepted or declined by the owner. \n\nYou can disable them by passing the following in the POST body when creating the bookings:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// Send email to owner with possible actions (enabled by default) \\n\\\"send_confirm_decline_email_to_owner\\\" : {\\n  \\\"enabled\\\": false\\n}\\n\\n// Send email to customer when booking is confirmed by owner (enabled by default) \\n\\\"notify_customer_by_email\\\": {\\n  \\\"enabled\\\": false\\n}\\n\\n// Send email to customer when booking is declined by owner (enabled by default) \\n\\\"notify_customer_declined_by_email\\\": {\\n  \\\"enabled\\\": false\\n}\\n\\n// Send email to customer if the booking get cancelled (enabled by default)\\n\\\"notify_customer_cancelled_by_email\\\": {\\n  \\\"enabled\\\": false\\n}\\n\\n// Send email to owner if the booking get cancelled (enabled by default)\\n\\\"notify_owner_cancelled_by_email\\\": {\\n  \\\"enabled\\\": false\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n## Other graphs\n\nYou can see all available actions/transitions for graphs [here](doc:bookingsgraphsid) - all email-related actions can be disabled with the same approach as above.","category":"56c6d51cfd00bb0d0016dac5","createdAt":"2016-02-19T09:25:25.230Z","excerpt":"","githubsync":"","isReference":true,"__v":10,"type":"basic","updates":[],"next":{"description":"","pages":[]},"order":7,"title":"Emails","version":"550bfb5522ccb01700a79469","api":{"params":[],"results":{"codes":[{"status":200,"language":"json","code":"{}","name":""},{"code":"{}","name":"","status":400,"language":"json"}]},"settings":"","url":"","auth":"required"},"link_url":"","childrenPages":[]}

Emails


By default, emails get sent out to owners and customers when bookings are created and move from state to state. Some emails take parameters, like a message, and you can choose to disable them if you'd like to handle communication yourself (e.g. with the help of [webhooks](doc:webhooks)). [block:callout] { "type": "success", "title": "Enabled by default", "body": "All emails are enabled by default and you have to manually disable them if you don't want to Timekit to send out any emails at all." } [/block] [block:api-header] { "type": "basic", "title": "Disabling emails" } [/block] In addition to taking event/customer data and creating calendar events, the `instant` graph also sends out emails and can trigger a webhook. You can see all available actions/transitions [here](doc:bookingsgraphsid) and below is a short list of how they can be configured (as JSON body data in your request): ## Graph: instant Bookings created using the "instant" graph only send out emails when the booking is created; one email for the owner and one for the customer. You can disable them by passing the following in the POST body when creating the bookings: [block:code] { "codes": [ { "code": "// Send email to the owner (enabled by default)\n\"notify_owner_by_email\": {\n \"enabled\": false\n}\n\n// Send email to the customer (enabled by default)\n\"notify_customer_by_email\": {\n \"enabled\": false\n}\n\n// Send email to customer if the booking get cancelled (enabled by default)\n\"notify_customer_cancelled_by_email\": {\n \"enabled\": false\n}\n\n// Send email to owner if the booking get cancelled (enabled by default)\n\"notify_owner_cancelled_by_email\": {\n \"enabled\": false\n}", "language": "json" } ] } [/block] ## Graph: confirm_decline Bookings created using the "confirm_decline" graph send out email an email to the owner when the booking is created, but also notifies the customer when the booking is either accepted or declined by the owner. You can disable them by passing the following in the POST body when creating the bookings: [block:code] { "codes": [ { "code": "// Send email to owner with possible actions (enabled by default) \n\"send_confirm_decline_email_to_owner\" : {\n \"enabled\": false\n}\n\n// Send email to customer when booking is confirmed by owner (enabled by default) \n\"notify_customer_by_email\": {\n \"enabled\": false\n}\n\n// Send email to customer when booking is declined by owner (enabled by default) \n\"notify_customer_declined_by_email\": {\n \"enabled\": false\n}\n\n// Send email to customer if the booking get cancelled (enabled by default)\n\"notify_customer_cancelled_by_email\": {\n \"enabled\": false\n}\n\n// Send email to owner if the booking get cancelled (enabled by default)\n\"notify_owner_cancelled_by_email\": {\n \"enabled\": false\n}", "language": "json" } ] } [/block] ## Other graphs You can see all available actions/transitions for graphs [here](doc:bookingsgraphsid) - all email-related actions can be disabled with the same approach as above.
By default, emails get sent out to owners and customers when bookings are created and move from state to state. Some emails take parameters, like a message, and you can choose to disable them if you'd like to handle communication yourself (e.g. with the help of [webhooks](doc:webhooks)). [block:callout] { "type": "success", "title": "Enabled by default", "body": "All emails are enabled by default and you have to manually disable them if you don't want to Timekit to send out any emails at all." } [/block] [block:api-header] { "type": "basic", "title": "Disabling emails" } [/block] In addition to taking event/customer data and creating calendar events, the `instant` graph also sends out emails and can trigger a webhook. You can see all available actions/transitions [here](doc:bookingsgraphsid) and below is a short list of how they can be configured (as JSON body data in your request): ## Graph: instant Bookings created using the "instant" graph only send out emails when the booking is created; one email for the owner and one for the customer. You can disable them by passing the following in the POST body when creating the bookings: [block:code] { "codes": [ { "code": "// Send email to the owner (enabled by default)\n\"notify_owner_by_email\": {\n \"enabled\": false\n}\n\n// Send email to the customer (enabled by default)\n\"notify_customer_by_email\": {\n \"enabled\": false\n}\n\n// Send email to customer if the booking get cancelled (enabled by default)\n\"notify_customer_cancelled_by_email\": {\n \"enabled\": false\n}\n\n// Send email to owner if the booking get cancelled (enabled by default)\n\"notify_owner_cancelled_by_email\": {\n \"enabled\": false\n}", "language": "json" } ] } [/block] ## Graph: confirm_decline Bookings created using the "confirm_decline" graph send out email an email to the owner when the booking is created, but also notifies the customer when the booking is either accepted or declined by the owner. You can disable them by passing the following in the POST body when creating the bookings: [block:code] { "codes": [ { "code": "// Send email to owner with possible actions (enabled by default) \n\"send_confirm_decline_email_to_owner\" : {\n \"enabled\": false\n}\n\n// Send email to customer when booking is confirmed by owner (enabled by default) \n\"notify_customer_by_email\": {\n \"enabled\": false\n}\n\n// Send email to customer when booking is declined by owner (enabled by default) \n\"notify_customer_declined_by_email\": {\n \"enabled\": false\n}\n\n// Send email to customer if the booking get cancelled (enabled by default)\n\"notify_customer_cancelled_by_email\": {\n \"enabled\": false\n}\n\n// Send email to owner if the booking get cancelled (enabled by default)\n\"notify_owner_cancelled_by_email\": {\n \"enabled\": false\n}", "language": "json" } ] } [/block] ## Other graphs You can see all available actions/transitions for graphs [here](doc:bookingsgraphsid) - all email-related actions can be disabled with the same approach as above.
{"_id":"583595cdab7af73700140f1a","category":"56c6d51cfd00bb0d0016dac5","link_external":false,"link_url":"","order":8,"type":"basic","body":"With Timekit webhooks, you can be notified as bookings move through different states in the booking engine. Just tell Timekit which states are important for your application and we'll let you know.\n\n* [Setting up webhooks](http://developers.timekit.io/v2/docs/webhooks#setting-up-webhooks)\n* [Webhook payloads](http://developers.timekit.io/v2/docs/webhooks#webhook-payloads)\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Setting up webhooks\"\n}\n[/block]\nWebhooks are configured on an app level. As an example, we can setup a webhook that notifies us when a new booking is created or when a booking has timed out because the payment didn't go through for some reason. There are endless use cases for webhooks.\n\nYou setup webhooks through our admin panel:\n[**https://admin.timekit.io/a/webhooks**](https://admin.timekit.io/a/webhooks)\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"If you can't spot the \\\"Webhooks\\\" tab in the admin panel, just enable Developer Mode in the profile dropdown.\"\n}\n[/block]\nYou can setup as many webhooks as you want for different graphs and different actions. Do note though that webhooks is not offered in our free plan.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Webhook payloads\"\n}\n[/block]\nWhen a webhook is triggered, the payload of the request looks similar to the JSON response you get when calling the [/bookings/:id](doc:bookingsid) endpoint. It includes the booking, calendar, customer and event resources:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"id\\\": \\\"c3c071de-6901-422f-bde6-86f5eaaf8476\\\",\\n  \\\"state\\\": \\\"confirmed\\\",\\n  \\\"graph\\\": \\\"instant\\\",\\n  \\\"completed\\\": false,\\n  \\\"created_at\\\": \\\"2016-11-24T13:34:54+0100\\\",\\n  \\\"updated_at\\\": \\\"2016-11-24T13:34:54+0100\\\",\\n  \\\"customers\\\": [\\n    {\\n      \\\"id\\\": \\\"65edeffb-410d-4286-9591-27548a9f31a2\\\",\\n      \\\"name\\\": \\\"Marty McFly\\\",\\n      \\\"email\\\": \\\"mcfly@example.com\\\",\\n      \\\"phone\\\": \\\"\\\",\\n      \\\"voip\\\": \\\"\\\",\\n      \\\"timezone\\\": \\\"Europe\\\\/Copenhagen\\\",\\n      \\\"meta\\\": \\\"{}\\\"\\n    }\\n  ],\\n  \\\"event\\\": {\\n    \\\"id\\\": \\\"bb1817fe-8dd6-4bfc-8606-a36a5871a82b\\\",\\n    \\\"what\\\": \\\"what\\\",\\n    \\\"where\\\": \\\"where\\\",\\n    \\\"description\\\": \\\"\\\",\\n    \\\"rsvp\\\": \\\"accepted\\\",\\n    \\\"allDay\\\": false,\\n    \\\"start\\\": \\\"2016-01-01T10:00:00+0100\\\",\\n    \\\"end\\\": \\\"2016-01-01T11:00:00+0100\\\",\\n    \\\"created_at\\\": \\\"2016-11-24T13:34:54+0100\\\",\\n    \\\"updated_at\\\": \\\"2016-11-24T13:34:54+0100\\\"\\n  },\\n  \\\"calendar\\\": {\\n    \\\"id\\\": \\\"d3bbcb33-2551-4806-8330-ecdec85c0c83\\\",\\n    \\\"provider_id\\\": \\\"provider_id\\\",\\n    \\\"provider_access\\\": \\\"owner\\\",\\n    \\\"provider_primary\\\": false,\\n    \\\"provider_sync\\\": false,\\n    \\\"name\\\": \\\"Quia nostrum voluptas quae aspernatur.\\\",\\n    \\\"description\\\": \\\"Quis et nam dolor recusandae ut eos.\\\",\\n    \\\"foregroundcolor\\\": \\\"#d9bfef\\\",\\n    \\\"backgroundcolor\\\": \\\"#22273e\\\",\\n    \\\"created_at\\\": \\\"2016-11-17T11:06:43+0100\\\",\\n    \\\"updated_at\\\": \\\"2016-11-17T11:06:43+0100\\\"\\n  }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"title\": \"Testing webhooks\"\n}\n[/block]\nAn easy way to test and inspect the webhook payload we send is to use a service like [requestb.in](http://requestb.in) - it allows you to quickly create a HTTP endpoint that you can give us and then inspect all requests made to it, straight from your browser!\n\n-----\n\nAt this point, if you have any questions about how to set up webhooks for your bookings, don't hesitate to hit us up on the chat.\n\nWe recommend that you also take a look at our guide \"[Building booking experiences with Timekit](doc:building-booking-experiences-with-timekit)\".","user":"57c7e8a25754fa1700b121df","api":{"results":{"codes":[{"status":200,"language":"json","code":"{}","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","auth":"required","params":[],"url":""},"excerpt":"Receive a webhook every time a booking transitions into a new state","hidden":false,"parentDoc":null,"updates":[],"sync_unique":"","__v":0,"createdAt":"2016-11-23T13:12:45.031Z","githubsync":"","isReference":true,"next":{"description":"","pages":[]},"project":"550ada512188a71900453199","slug":"webhooks","title":"Webhooks","version":"550bfb5522ccb01700a79469","childrenPages":[]}

Webhooks

Receive a webhook every time a booking transitions into a new state

With Timekit webhooks, you can be notified as bookings move through different states in the booking engine. Just tell Timekit which states are important for your application and we'll let you know. * [Setting up webhooks](http://developers.timekit.io/v2/docs/webhooks#setting-up-webhooks) * [Webhook payloads](http://developers.timekit.io/v2/docs/webhooks#webhook-payloads) [block:api-header] { "type": "basic", "title": "Setting up webhooks" } [/block] Webhooks are configured on an app level. As an example, we can setup a webhook that notifies us when a new booking is created or when a booking has timed out because the payment didn't go through for some reason. There are endless use cases for webhooks. You setup webhooks through our admin panel: [**https://admin.timekit.io/a/webhooks**](https://admin.timekit.io/a/webhooks) [block:callout] { "type": "warning", "body": "If you can't spot the \"Webhooks\" tab in the admin panel, just enable Developer Mode in the profile dropdown." } [/block] You can setup as many webhooks as you want for different graphs and different actions. Do note though that webhooks is not offered in our free plan. [block:api-header] { "type": "basic", "title": "Webhook payloads" } [/block] When a webhook is triggered, the payload of the request looks similar to the JSON response you get when calling the [/bookings/:id](doc:bookingsid) endpoint. It includes the booking, calendar, customer and event resources: [block:code] { "codes": [ { "code": "{\n \"id\": \"c3c071de-6901-422f-bde6-86f5eaaf8476\",\n \"state\": \"confirmed\",\n \"graph\": \"instant\",\n \"completed\": false,\n \"created_at\": \"2016-11-24T13:34:54+0100\",\n \"updated_at\": \"2016-11-24T13:34:54+0100\",\n \"customers\": [\n {\n \"id\": \"65edeffb-410d-4286-9591-27548a9f31a2\",\n \"name\": \"Marty McFly\",\n \"email\": \"mcfly@example.com\",\n \"phone\": \"\",\n \"voip\": \"\",\n \"timezone\": \"Europe\\/Copenhagen\",\n \"meta\": \"{}\"\n }\n ],\n \"event\": {\n \"id\": \"bb1817fe-8dd6-4bfc-8606-a36a5871a82b\",\n \"what\": \"what\",\n \"where\": \"where\",\n \"description\": \"\",\n \"rsvp\": \"accepted\",\n \"allDay\": false,\n \"start\": \"2016-01-01T10:00:00+0100\",\n \"end\": \"2016-01-01T11:00:00+0100\",\n \"created_at\": \"2016-11-24T13:34:54+0100\",\n \"updated_at\": \"2016-11-24T13:34:54+0100\"\n },\n \"calendar\": {\n \"id\": \"d3bbcb33-2551-4806-8330-ecdec85c0c83\",\n \"provider_id\": \"provider_id\",\n \"provider_access\": \"owner\",\n \"provider_primary\": false,\n \"provider_sync\": false,\n \"name\": \"Quia nostrum voluptas quae aspernatur.\",\n \"description\": \"Quis et nam dolor recusandae ut eos.\",\n \"foregroundcolor\": \"#d9bfef\",\n \"backgroundcolor\": \"#22273e\",\n \"created_at\": \"2016-11-17T11:06:43+0100\",\n \"updated_at\": \"2016-11-17T11:06:43+0100\"\n }\n}", "language": "json" } ] } [/block] [block:api-header] { "title": "Testing webhooks" } [/block] An easy way to test and inspect the webhook payload we send is to use a service like [requestb.in](http://requestb.in) - it allows you to quickly create a HTTP endpoint that you can give us and then inspect all requests made to it, straight from your browser! ----- At this point, if you have any questions about how to set up webhooks for your bookings, don't hesitate to hit us up on the chat. We recommend that you also take a look at our guide "[Building booking experiences with Timekit](doc:building-booking-experiences-with-timekit)".
With Timekit webhooks, you can be notified as bookings move through different states in the booking engine. Just tell Timekit which states are important for your application and we'll let you know. * [Setting up webhooks](http://developers.timekit.io/v2/docs/webhooks#setting-up-webhooks) * [Webhook payloads](http://developers.timekit.io/v2/docs/webhooks#webhook-payloads) [block:api-header] { "type": "basic", "title": "Setting up webhooks" } [/block] Webhooks are configured on an app level. As an example, we can setup a webhook that notifies us when a new booking is created or when a booking has timed out because the payment didn't go through for some reason. There are endless use cases for webhooks. You setup webhooks through our admin panel: [**https://admin.timekit.io/a/webhooks**](https://admin.timekit.io/a/webhooks) [block:callout] { "type": "warning", "body": "If you can't spot the \"Webhooks\" tab in the admin panel, just enable Developer Mode in the profile dropdown." } [/block] You can setup as many webhooks as you want for different graphs and different actions. Do note though that webhooks is not offered in our free plan. [block:api-header] { "type": "basic", "title": "Webhook payloads" } [/block] When a webhook is triggered, the payload of the request looks similar to the JSON response you get when calling the [/bookings/:id](doc:bookingsid) endpoint. It includes the booking, calendar, customer and event resources: [block:code] { "codes": [ { "code": "{\n \"id\": \"c3c071de-6901-422f-bde6-86f5eaaf8476\",\n \"state\": \"confirmed\",\n \"graph\": \"instant\",\n \"completed\": false,\n \"created_at\": \"2016-11-24T13:34:54+0100\",\n \"updated_at\": \"2016-11-24T13:34:54+0100\",\n \"customers\": [\n {\n \"id\": \"65edeffb-410d-4286-9591-27548a9f31a2\",\n \"name\": \"Marty McFly\",\n \"email\": \"mcfly@example.com\",\n \"phone\": \"\",\n \"voip\": \"\",\n \"timezone\": \"Europe\\/Copenhagen\",\n \"meta\": \"{}\"\n }\n ],\n \"event\": {\n \"id\": \"bb1817fe-8dd6-4bfc-8606-a36a5871a82b\",\n \"what\": \"what\",\n \"where\": \"where\",\n \"description\": \"\",\n \"rsvp\": \"accepted\",\n \"allDay\": false,\n \"start\": \"2016-01-01T10:00:00+0100\",\n \"end\": \"2016-01-01T11:00:00+0100\",\n \"created_at\": \"2016-11-24T13:34:54+0100\",\n \"updated_at\": \"2016-11-24T13:34:54+0100\"\n },\n \"calendar\": {\n \"id\": \"d3bbcb33-2551-4806-8330-ecdec85c0c83\",\n \"provider_id\": \"provider_id\",\n \"provider_access\": \"owner\",\n \"provider_primary\": false,\n \"provider_sync\": false,\n \"name\": \"Quia nostrum voluptas quae aspernatur.\",\n \"description\": \"Quis et nam dolor recusandae ut eos.\",\n \"foregroundcolor\": \"#d9bfef\",\n \"backgroundcolor\": \"#22273e\",\n \"created_at\": \"2016-11-17T11:06:43+0100\",\n \"updated_at\": \"2016-11-17T11:06:43+0100\"\n }\n}", "language": "json" } ] } [/block] [block:api-header] { "title": "Testing webhooks" } [/block] An easy way to test and inspect the webhook payload we send is to use a service like [requestb.in](http://requestb.in) - it allows you to quickly create a HTTP endpoint that you can give us and then inspect all requests made to it, straight from your browser! ----- At this point, if you have any questions about how to set up webhooks for your bookings, don't hesitate to hit us up on the chat. We recommend that you also take a look at our guide "[Building booking experiences with Timekit](doc:building-booking-experiences-with-timekit)".
{"_id":"58341b5a88081719004118bc","api":{"auth":"required","params":[],"url":"","results":{"codes":[{"language":"json","code":"{}","name":"","status":200},{"code":"{}","name":"","status":400,"language":"json"}]},"settings":""},"category":"56c6d51cfd00bb0d0016dac5","type":"basic","updates":[],"user":"57c7e8a25754fa1700b121df","body":"There are a few ways in which you can setup Timekit to send out notifications to users/resources and customers, either before or after a booking. In this guide, we'll go over all of them.\n\n* [Reminder emails](http://developers.timekit.io/v2/docs/notifications#reminder-emails)\n* [Webhook notifications](http://developers.timekit.io/v2/docs/notifications#webhook-notifications)\n* [App level notifications](http://developers.timekit.io/v2/docs/notifications#app-level-notifications)\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Reminder emails\"\n}\n[/block]\nThe easiest way to send reminder emails before a booking is to use the built-in reminder emails in Timekit. If you prefer using your own emails, jump to the next section where we talk about using webhooks to achieve the same result.\n\nWhen you create a booking, you can pass an array of `event_notifications` along with the booking. Notifications can have one of two types; email or webhook. If you choose email, Timekit will use its default reminder email template.\n\nLet's say we want to send a reminder email to both the owner and the customer an hour before the booking begins. This is pretty straightforward with Timekit:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// Replace {{calendar_id}} with the id of the calendar\\n{\\n\\t\\\"graph\\\": \\\"instant\\\",\\n\\t\\\"action\\\": \\\"confirm\\\",\\n\\t\\\"customer\\\": {\\n\\t\\t\\\"name\\\": \\\"Marty McFly\\\",\\n    \\\"email\\\": \\\"marty.mcfly@timekit.io\\\"\\n\\t},\\n\\t\\\"event\\\": {\\n\\t\\t\\\"start\\\": \\\"2016-11-23 15:00:00\\\",\\n\\t\\t\\\"end\\\": \\\"2016-11-23 16:00:00\\\",\\n\\t\\t\\\"what\\\": \\\"Mens haircut\\\",\\n\\t\\t\\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n\\t\\t\\\"calendar_id\\\": \\\"{{calendar_id}}\\\"\\n\\t},\\n\\t\\\"event_notifications\\\": [\\n\\t\\t{\\n\\t\\t\\t\\\"type\\\": \\\"email\\\",\\n\\t\\t\\t\\\"settings\\\": {\\n\\t\\t\\t\\t\\\"recipient\\\": \\\"customer\\\",\\n\\t\\t\\t\\t\\\"subject\\\": \\\"Upcoming booking\\\"\\n\\t\\t\\t},\\n\\t\\t\\t\\\"when\\\": {\\n\\t\\t\\t\\t\\\"type\\\": \\\"before\\\",\\n\\t\\t\\t\\t\\\"unit\\\": \\\"mins\\\",\\n\\t\\t\\t\\t\\\"time\\\": 60\\n\\t\\t\\t}\\n\\t\\t},\\n\\t\\t{\\n\\t\\t\\t\\\"type\\\": \\\"email\\\",\\n\\t\\t\\t\\\"settings\\\": {\\n\\t\\t\\t\\t\\\"recipient\\\": \\\"owner\\\",\\n\\t\\t\\t\\t\\\"subject\\\": \\\"Upcoming booking\\\"\\n\\t\\t\\t},\\n\\t\\t\\t\\\"when\\\": {\\n\\t\\t\\t\\t\\\"type\\\": \\\"before\\\",\\n\\t\\t\\t\\t\\\"unit\\\": \\\"mins\\\",\\n\\t\\t\\t\\t\\\"time\\\": 60\\n\\t\\t\\t}\\n\\t\\t}\\n\\t]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nThis is the JSON we would [POST] to create the booking. 60 minutes before the booking begins, an email will be sent to both the owner and the customer with a reminder. The email looks something like this:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/908c668-Screen_Shot_2016-11-23_at_14.56.42.png\",\n        \"Screen Shot 2016-11-23 at 14.56.42.png\",\n        1372,\n        720,\n        \"#f7f8f9\"\n      ]\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Webhook notifications\"\n}\n[/block]\nIn addition to emails, you can also set up webhook notifications that can be fired either before or after the booking begins. This is useful if you want to send your own emails, and just want to know when to send them.\n\nWebhooks can be used for many other things than just reminders. Maybe you want to send out a questionnaire to your customers a day after the booking?\n\nUsing the latter example, let's set up a webhook notification to go out 24 hours after the booking began. This is the JSON we will [POST] to create the booking:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n\\t\\\"graph\\\": \\\"instant\\\",\\n\\t\\\"action\\\": \\\"confirm\\\",\\n\\t\\\"customer\\\": {\\n\\t\\t\\\"name\\\": \\\"Marty McFly\\\",\\n    \\t\\\"email\\\": \\\"marty.mcfly@timekit.io\\\"\\n\\t},\\n\\t\\\"event\\\": {\\n\\t\\t\\\"start\\\": \\\"2016-11-23 15:00:00\\\",\\n\\t\\t\\\"end\\\": \\\"2016-11-23 16:00:00\\\",\\n\\t\\t\\\"what\\\": \\\"Mens haircut\\\",\\n\\t\\t\\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n\\t\\t\\\"calendar_id\\\": \\\"{{calendar_id}}\\\"\\n\\t},\\n\\t\\\"event_notifications\\\": [\\n\\t\\t{\\n\\t\\t\\t\\\"type\\\": \\\"webhook\\\",\\n\\t\\t\\t\\\"settings\\\": {\\n\\t\\t\\t\\t\\\"url\\\": \\\"https://example.com/some-endpoint\\\",\\n\\t\\t\\t\\t\\\"method\\\": \\\"post\\\",\\n\\t\\t\\t\\t\\\"expected_response_code\\\": 200\\n\\t\\t\\t},\\n\\t\\t\\t\\\"when\\\": {\\n\\t\\t\\t\\t\\\"type\\\": \\\"after\\\",\\n\\t\\t\\t\\t\\\"unit\\\": \\\"hours\\\",\\n\\t\\t\\t\\t\\\"time\\\": 24\\n\\t\\t\\t}\\n\\t\\t}\\n\\t]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n24 hours after the booking begins, Timekit will then send a POST request to `https://example.com/some-endpoint` and expect a 200 response.\n\nThe payload of the webhook request looks similar to the response you get when you [GET] the [/bookings/:id](doc:bookingsid) endpoint.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"App level notifications\"\n}\n[/block]\nInstead of configuring notifications for each individual booking, they can also be configured on an app level. If you set notifications up on the app level, they will be created for each booking created under that app.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"Sending an array of `event_notifications` will overwrite the app level notifications for the booking.\",\n  \"title\": \"Overwriting app level notifications\"\n}\n[/block]\nLet's say we always (at least by default) want to send a reminder email to the owner and customer before a booking. We can update our application settings to include the app level notifications. All this requires is a [PUT] request with the same `event_notifications` array to the [/apps/:slug](doc:appsslug) endpoint:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n\\t\\\"event_notifications\\\": [\\n\\t\\t{\\n\\t\\t\\t\\\"type\\\": \\\"email\\\",\\n\\t\\t\\t\\\"settings\\\": {\\n\\t\\t\\t\\t\\\"recipient\\\": \\\"customer\\\",\\n\\t\\t\\t\\t\\\"subject\\\": \\\"Upcoming booking\\\"\\n\\t\\t\\t},\\n\\t\\t\\t\\\"when\\\": {\\n\\t\\t\\t\\t\\\"type\\\": \\\"before\\\",\\n\\t\\t\\t\\t\\\"unit\\\": \\\"mins\\\",\\n\\t\\t\\t\\t\\\"time\\\": 60\\n\\t\\t\\t}\\n\\t\\t},\\n\\t\\t{\\n\\t\\t\\t\\\"type\\\": \\\"email\\\",\\n\\t\\t\\t\\\"settings\\\": {\\n\\t\\t\\t\\t\\\"recipient\\\": \\\"owner\\\",\\n\\t\\t\\t\\t\\\"subject\\\": \\\"Upcoming booking\\\"\\n\\t\\t\\t},\\n\\t\\t\\t\\\"when\\\": {\\n\\t\\t\\t\\t\\\"type\\\": \\\"before\\\",\\n\\t\\t\\t\\t\\\"unit\\\": \\\"mins\\\",\\n\\t\\t\\t\\t\\\"time\\\": 60\\n\\t\\t\\t}\\n\\t\\t}\\n\\t]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nNow, every time a booking is created, two notifications will be created: One for the owner and one for the customer.\n\nAaaand that's it! If you have any questions about how to set up notifications for your bookings, hit us up on the chat.\n\nWe recommend that you also take a look at our guide \"[Building booking experiences with Timekit](doc:building-booking-experiences-with-timekit)\".","githubsync":"","hidden":false,"link_external":false,"link_url":"","parentDoc":null,"slug":"notifications","__v":0,"createdAt":"2016-11-22T10:18:02.231Z","isReference":true,"excerpt":"Send out notifications or listen for webhooks before or after events","next":{"pages":[],"description":""},"order":9,"project":"550ada512188a71900453199","sync_unique":"","title":"Reminders/notifications","version":"550bfb5522ccb01700a79469","childrenPages":[]}

Reminders/notifications

Send out notifications or listen for webhooks before or after events

There are a few ways in which you can setup Timekit to send out notifications to users/resources and customers, either before or after a booking. In this guide, we'll go over all of them. * [Reminder emails](http://developers.timekit.io/v2/docs/notifications#reminder-emails) * [Webhook notifications](http://developers.timekit.io/v2/docs/notifications#webhook-notifications) * [App level notifications](http://developers.timekit.io/v2/docs/notifications#app-level-notifications) [block:api-header] { "type": "basic", "title": "Reminder emails" } [/block] The easiest way to send reminder emails before a booking is to use the built-in reminder emails in Timekit. If you prefer using your own emails, jump to the next section where we talk about using webhooks to achieve the same result. When you create a booking, you can pass an array of `event_notifications` along with the booking. Notifications can have one of two types; email or webhook. If you choose email, Timekit will use its default reminder email template. Let's say we want to send a reminder email to both the owner and the customer an hour before the booking begins. This is pretty straightforward with Timekit: [block:code] { "codes": [ { "code": "// Replace {{calendar_id}} with the id of the calendar\n{\n\t\"graph\": \"instant\",\n\t\"action\": \"confirm\",\n\t\"customer\": {\n\t\t\"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\"\n\t},\n\t\"event\": {\n\t\t\"start\": \"2016-11-23 15:00:00\",\n\t\t\"end\": \"2016-11-23 16:00:00\",\n\t\t\"what\": \"Mens haircut\",\n\t\t\"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n\t\t\"calendar_id\": \"{{calendar_id}}\"\n\t},\n\t\"event_notifications\": [\n\t\t{\n\t\t\t\"type\": \"email\",\n\t\t\t\"settings\": {\n\t\t\t\t\"recipient\": \"customer\",\n\t\t\t\t\"subject\": \"Upcoming booking\"\n\t\t\t},\n\t\t\t\"when\": {\n\t\t\t\t\"type\": \"before\",\n\t\t\t\t\"unit\": \"mins\",\n\t\t\t\t\"time\": 60\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"type\": \"email\",\n\t\t\t\"settings\": {\n\t\t\t\t\"recipient\": \"owner\",\n\t\t\t\t\"subject\": \"Upcoming booking\"\n\t\t\t},\n\t\t\t\"when\": {\n\t\t\t\t\"type\": \"before\",\n\t\t\t\t\"unit\": \"mins\",\n\t\t\t\t\"time\": 60\n\t\t\t}\n\t\t}\n\t]\n}", "language": "json" } ] } [/block] This is the JSON we would [POST] to create the booking. 60 minutes before the booking begins, an email will be sent to both the owner and the customer with a reminder. The email looks something like this: [block:image] { "images": [ { "image": [ "https://files.readme.io/908c668-Screen_Shot_2016-11-23_at_14.56.42.png", "Screen Shot 2016-11-23 at 14.56.42.png", 1372, 720, "#f7f8f9" ] } ] } [/block] [block:api-header] { "type": "basic", "title": "Webhook notifications" } [/block] In addition to emails, you can also set up webhook notifications that can be fired either before or after the booking begins. This is useful if you want to send your own emails, and just want to know when to send them. Webhooks can be used for many other things than just reminders. Maybe you want to send out a questionnaire to your customers a day after the booking? Using the latter example, let's set up a webhook notification to go out 24 hours after the booking began. This is the JSON we will [POST] to create the booking: [block:code] { "codes": [ { "code": "{\n\t\"graph\": \"instant\",\n\t\"action\": \"confirm\",\n\t\"customer\": {\n\t\t\"name\": \"Marty McFly\",\n \t\"email\": \"marty.mcfly@timekit.io\"\n\t},\n\t\"event\": {\n\t\t\"start\": \"2016-11-23 15:00:00\",\n\t\t\"end\": \"2016-11-23 16:00:00\",\n\t\t\"what\": \"Mens haircut\",\n\t\t\"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n\t\t\"calendar_id\": \"{{calendar_id}}\"\n\t},\n\t\"event_notifications\": [\n\t\t{\n\t\t\t\"type\": \"webhook\",\n\t\t\t\"settings\": {\n\t\t\t\t\"url\": \"https://example.com/some-endpoint\",\n\t\t\t\t\"method\": \"post\",\n\t\t\t\t\"expected_response_code\": 200\n\t\t\t},\n\t\t\t\"when\": {\n\t\t\t\t\"type\": \"after\",\n\t\t\t\t\"unit\": \"hours\",\n\t\t\t\t\"time\": 24\n\t\t\t}\n\t\t}\n\t]\n}", "language": "json" } ] } [/block] 24 hours after the booking begins, Timekit will then send a POST request to `https://example.com/some-endpoint` and expect a 200 response. The payload of the webhook request looks similar to the response you get when you [GET] the [/bookings/:id](doc:bookingsid) endpoint. [block:api-header] { "type": "basic", "title": "App level notifications" } [/block] Instead of configuring notifications for each individual booking, they can also be configured on an app level. If you set notifications up on the app level, they will be created for each booking created under that app. [block:callout] { "type": "warning", "body": "Sending an array of `event_notifications` will overwrite the app level notifications for the booking.", "title": "Overwriting app level notifications" } [/block] Let's say we always (at least by default) want to send a reminder email to the owner and customer before a booking. We can update our application settings to include the app level notifications. All this requires is a [PUT] request with the same `event_notifications` array to the [/apps/:slug](doc:appsslug) endpoint: [block:code] { "codes": [ { "code": "{\n\t\"event_notifications\": [\n\t\t{\n\t\t\t\"type\": \"email\",\n\t\t\t\"settings\": {\n\t\t\t\t\"recipient\": \"customer\",\n\t\t\t\t\"subject\": \"Upcoming booking\"\n\t\t\t},\n\t\t\t\"when\": {\n\t\t\t\t\"type\": \"before\",\n\t\t\t\t\"unit\": \"mins\",\n\t\t\t\t\"time\": 60\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"type\": \"email\",\n\t\t\t\"settings\": {\n\t\t\t\t\"recipient\": \"owner\",\n\t\t\t\t\"subject\": \"Upcoming booking\"\n\t\t\t},\n\t\t\t\"when\": {\n\t\t\t\t\"type\": \"before\",\n\t\t\t\t\"unit\": \"mins\",\n\t\t\t\t\"time\": 60\n\t\t\t}\n\t\t}\n\t]\n}", "language": "json" } ] } [/block] Now, every time a booking is created, two notifications will be created: One for the owner and one for the customer. Aaaand that's it! If you have any questions about how to set up notifications for your bookings, hit us up on the chat. We recommend that you also take a look at our guide "[Building booking experiences with Timekit](doc:building-booking-experiences-with-timekit)".
There are a few ways in which you can setup Timekit to send out notifications to users/resources and customers, either before or after a booking. In this guide, we'll go over all of them. * [Reminder emails](http://developers.timekit.io/v2/docs/notifications#reminder-emails) * [Webhook notifications](http://developers.timekit.io/v2/docs/notifications#webhook-notifications) * [App level notifications](http://developers.timekit.io/v2/docs/notifications#app-level-notifications) [block:api-header] { "type": "basic", "title": "Reminder emails" } [/block] The easiest way to send reminder emails before a booking is to use the built-in reminder emails in Timekit. If you prefer using your own emails, jump to the next section where we talk about using webhooks to achieve the same result. When you create a booking, you can pass an array of `event_notifications` along with the booking. Notifications can have one of two types; email or webhook. If you choose email, Timekit will use its default reminder email template. Let's say we want to send a reminder email to both the owner and the customer an hour before the booking begins. This is pretty straightforward with Timekit: [block:code] { "codes": [ { "code": "// Replace {{calendar_id}} with the id of the calendar\n{\n\t\"graph\": \"instant\",\n\t\"action\": \"confirm\",\n\t\"customer\": {\n\t\t\"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\"\n\t},\n\t\"event\": {\n\t\t\"start\": \"2016-11-23 15:00:00\",\n\t\t\"end\": \"2016-11-23 16:00:00\",\n\t\t\"what\": \"Mens haircut\",\n\t\t\"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n\t\t\"calendar_id\": \"{{calendar_id}}\"\n\t},\n\t\"event_notifications\": [\n\t\t{\n\t\t\t\"type\": \"email\",\n\t\t\t\"settings\": {\n\t\t\t\t\"recipient\": \"customer\",\n\t\t\t\t\"subject\": \"Upcoming booking\"\n\t\t\t},\n\t\t\t\"when\": {\n\t\t\t\t\"type\": \"before\",\n\t\t\t\t\"unit\": \"mins\",\n\t\t\t\t\"time\": 60\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"type\": \"email\",\n\t\t\t\"settings\": {\n\t\t\t\t\"recipient\": \"owner\",\n\t\t\t\t\"subject\": \"Upcoming booking\"\n\t\t\t},\n\t\t\t\"when\": {\n\t\t\t\t\"type\": \"before\",\n\t\t\t\t\"unit\": \"mins\",\n\t\t\t\t\"time\": 60\n\t\t\t}\n\t\t}\n\t]\n}", "language": "json" } ] } [/block] This is the JSON we would [POST] to create the booking. 60 minutes before the booking begins, an email will be sent to both the owner and the customer with a reminder. The email looks something like this: [block:image] { "images": [ { "image": [ "https://files.readme.io/908c668-Screen_Shot_2016-11-23_at_14.56.42.png", "Screen Shot 2016-11-23 at 14.56.42.png", 1372, 720, "#f7f8f9" ] } ] } [/block] [block:api-header] { "type": "basic", "title": "Webhook notifications" } [/block] In addition to emails, you can also set up webhook notifications that can be fired either before or after the booking begins. This is useful if you want to send your own emails, and just want to know when to send them. Webhooks can be used for many other things than just reminders. Maybe you want to send out a questionnaire to your customers a day after the booking? Using the latter example, let's set up a webhook notification to go out 24 hours after the booking began. This is the JSON we will [POST] to create the booking: [block:code] { "codes": [ { "code": "{\n\t\"graph\": \"instant\",\n\t\"action\": \"confirm\",\n\t\"customer\": {\n\t\t\"name\": \"Marty McFly\",\n \t\"email\": \"marty.mcfly@timekit.io\"\n\t},\n\t\"event\": {\n\t\t\"start\": \"2016-11-23 15:00:00\",\n\t\t\"end\": \"2016-11-23 16:00:00\",\n\t\t\"what\": \"Mens haircut\",\n\t\t\"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n\t\t\"calendar_id\": \"{{calendar_id}}\"\n\t},\n\t\"event_notifications\": [\n\t\t{\n\t\t\t\"type\": \"webhook\",\n\t\t\t\"settings\": {\n\t\t\t\t\"url\": \"https://example.com/some-endpoint\",\n\t\t\t\t\"method\": \"post\",\n\t\t\t\t\"expected_response_code\": 200\n\t\t\t},\n\t\t\t\"when\": {\n\t\t\t\t\"type\": \"after\",\n\t\t\t\t\"unit\": \"hours\",\n\t\t\t\t\"time\": 24\n\t\t\t}\n\t\t}\n\t]\n}", "language": "json" } ] } [/block] 24 hours after the booking begins, Timekit will then send a POST request to `https://example.com/some-endpoint` and expect a 200 response. The payload of the webhook request looks similar to the response you get when you [GET] the [/bookings/:id](doc:bookingsid) endpoint. [block:api-header] { "type": "basic", "title": "App level notifications" } [/block] Instead of configuring notifications for each individual booking, they can also be configured on an app level. If you set notifications up on the app level, they will be created for each booking created under that app. [block:callout] { "type": "warning", "body": "Sending an array of `event_notifications` will overwrite the app level notifications for the booking.", "title": "Overwriting app level notifications" } [/block] Let's say we always (at least by default) want to send a reminder email to the owner and customer before a booking. We can update our application settings to include the app level notifications. All this requires is a [PUT] request with the same `event_notifications` array to the [/apps/:slug](doc:appsslug) endpoint: [block:code] { "codes": [ { "code": "{\n\t\"event_notifications\": [\n\t\t{\n\t\t\t\"type\": \"email\",\n\t\t\t\"settings\": {\n\t\t\t\t\"recipient\": \"customer\",\n\t\t\t\t\"subject\": \"Upcoming booking\"\n\t\t\t},\n\t\t\t\"when\": {\n\t\t\t\t\"type\": \"before\",\n\t\t\t\t\"unit\": \"mins\",\n\t\t\t\t\"time\": 60\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"type\": \"email\",\n\t\t\t\"settings\": {\n\t\t\t\t\"recipient\": \"owner\",\n\t\t\t\t\"subject\": \"Upcoming booking\"\n\t\t\t},\n\t\t\t\"when\": {\n\t\t\t\t\"type\": \"before\",\n\t\t\t\t\"unit\": \"mins\",\n\t\t\t\t\"time\": 60\n\t\t\t}\n\t\t}\n\t]\n}", "language": "json" } ] } [/block] Now, every time a booking is created, two notifications will be created: One for the owner and one for the customer. Aaaand that's it! If you have any questions about how to set up notifications for your bookings, hit us up on the chat. We recommend that you also take a look at our guide "[Building booking experiences with Timekit](doc:building-booking-experiences-with-timekit)".
{"_id":"5829aabc6a1d1f0f00b944d2","hidden":false,"isReference":true,"link_url":"","parentDoc":null,"updates":[],"user":"57c7e8a25754fa1700b121df","__v":0,"category":"56c6d51cfd00bb0d0016dac5","link_external":false,"project":"550ada512188a71900453199","slug":"cancellations","sync_unique":"","type":"basic","version":"550bfb5522ccb01700a79469","githubsync":"","order":10,"title":"Cancellations","api":{"url":"","results":{"codes":[{"language":"json","code":"{}","name":"","status":200},{"code":"{}","name":"","status":400,"language":"json"}]},"settings":"","auth":"required","params":[]},"body":"Using the [/bookings/:id/:action](doc:bookingsidaction) endpoint, you can cancel a booking and make sure that both owner and customer is notified.\n\n* [Cancelling a booking](http://developers.timekit.io/v2/docs/cancellations#canceling-a-booking)\n* [Cancelling a group booking](http://developers.timekit.io/v2/docs/cancellations#cancelling-a-group-booking)\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Cancelling a booking\"\n}\n[/block]\nCancelling a 1-on-1 booking (using the `confirm_decline` or `instant` graphs), is done by sending a PUT request to the [/bookings/:id/:action](doc:bookingsidaction) endpoint. It looks something like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example (replace :id)\\n# [PUT] /bookings/:id/cancel\\ncurl -X POST \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n          \\\"cancel\\\": {\\n            \\\"message\\\": \\\"Sorry, gotta fix the DeLorean\\\"\\n          }\\n        }' \\\\\\n     https://api.timekit.io/v2/bookings/:id/cancel\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nAfter calling the `cancel` action, the booking will enter a `cancelled` state and a notification email will be sent to both the owner and customer.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Cancelling a group booking\"\n}\n[/block]\nCancelling a group booking is very similar to cancelling a 1-on-1 booking. For the owner booking (using the `group_owner` graph), it's the exact same process using the [/bookings/:id/:action](doc:bookingsidaction) endpoint. After the owner booking has been cancelled, all the customers will receive a notification via email.\n\nCancelling a customer group booking (using the `group_customer` graph) is done with the `cancel_by_customer` action, instead of the usual `cancel` action, and looks like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Request example (replace :customer_booking_id)\\n# [PUT] /bookings/:customer_booking_id/cancel_by_customer\\ncurl -X POST \\\\\\n     -H 'Timekit-App: back-to-the-future' \\\\\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\\\\n     -d '{\\n          \\\"cancel_by_customer\\\": {\\n            \\\"message\\\": \\\"Sorry, I'm not so (Mc)fly today\\\"\\n          }\\n        }' \\\\\\n     https://api.timekit.io/v2/bookings/:customer_booking_id/cancel_by_customer\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nAfter the customer has cancelled the booking, a notification is sent to the owner via email.","createdAt":"2016-11-14T12:14:52.633Z","excerpt":"How to cancel a booking as a owner or a customer","next":{"pages":[],"description":""},"childrenPages":[]}

Cancellations

How to cancel a booking as a owner or a customer

Using the [/bookings/:id/:action](doc:bookingsidaction) endpoint, you can cancel a booking and make sure that both owner and customer is notified. * [Cancelling a booking](http://developers.timekit.io/v2/docs/cancellations#canceling-a-booking) * [Cancelling a group booking](http://developers.timekit.io/v2/docs/cancellations#cancelling-a-group-booking) [block:api-header] { "type": "basic", "title": "Cancelling a booking" } [/block] Cancelling a 1-on-1 booking (using the `confirm_decline` or `instant` graphs), is done by sending a PUT request to the [/bookings/:id/:action](doc:bookingsidaction) endpoint. It looks something like this: [block:code] { "codes": [ { "code": "# Request example (replace :id)\n# [PUT] /bookings/:id/cancel\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"cancel\": {\n \"message\": \"Sorry, gotta fix the DeLorean\"\n }\n }' \\\n https://api.timekit.io/v2/bookings/:id/cancel", "language": "curl" } ] } [/block] After calling the `cancel` action, the booking will enter a `cancelled` state and a notification email will be sent to both the owner and customer. [block:api-header] { "type": "basic", "title": "Cancelling a group booking" } [/block] Cancelling a group booking is very similar to cancelling a 1-on-1 booking. For the owner booking (using the `group_owner` graph), it's the exact same process using the [/bookings/:id/:action](doc:bookingsidaction) endpoint. After the owner booking has been cancelled, all the customers will receive a notification via email. Cancelling a customer group booking (using the `group_customer` graph) is done with the `cancel_by_customer` action, instead of the usual `cancel` action, and looks like this: [block:code] { "codes": [ { "code": "# Request example (replace :customer_booking_id)\n# [PUT] /bookings/:customer_booking_id/cancel_by_customer\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"cancel_by_customer\": {\n \"message\": \"Sorry, I'm not so (Mc)fly today\"\n }\n }' \\\n https://api.timekit.io/v2/bookings/:customer_booking_id/cancel_by_customer", "language": "curl" } ] } [/block] After the customer has cancelled the booking, a notification is sent to the owner via email.
Using the [/bookings/:id/:action](doc:bookingsidaction) endpoint, you can cancel a booking and make sure that both owner and customer is notified. * [Cancelling a booking](http://developers.timekit.io/v2/docs/cancellations#canceling-a-booking) * [Cancelling a group booking](http://developers.timekit.io/v2/docs/cancellations#cancelling-a-group-booking) [block:api-header] { "type": "basic", "title": "Cancelling a booking" } [/block] Cancelling a 1-on-1 booking (using the `confirm_decline` or `instant` graphs), is done by sending a PUT request to the [/bookings/:id/:action](doc:bookingsidaction) endpoint. It looks something like this: [block:code] { "codes": [ { "code": "# Request example (replace :id)\n# [PUT] /bookings/:id/cancel\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"cancel\": {\n \"message\": \"Sorry, gotta fix the DeLorean\"\n }\n }' \\\n https://api.timekit.io/v2/bookings/:id/cancel", "language": "curl" } ] } [/block] After calling the `cancel` action, the booking will enter a `cancelled` state and a notification email will be sent to both the owner and customer. [block:api-header] { "type": "basic", "title": "Cancelling a group booking" } [/block] Cancelling a group booking is very similar to cancelling a 1-on-1 booking. For the owner booking (using the `group_owner` graph), it's the exact same process using the [/bookings/:id/:action](doc:bookingsidaction) endpoint. After the owner booking has been cancelled, all the customers will receive a notification via email. Cancelling a customer group booking (using the `group_customer` graph) is done with the `cancel_by_customer` action, instead of the usual `cancel` action, and looks like this: [block:code] { "codes": [ { "code": "# Request example (replace :customer_booking_id)\n# [PUT] /bookings/:customer_booking_id/cancel_by_customer\ncurl -X POST \\\n -H 'Timekit-App: back-to-the-future' \\\n -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n -d '{\n \"cancel_by_customer\": {\n \"message\": \"Sorry, I'm not so (Mc)fly today\"\n }\n }' \\\n https://api.timekit.io/v2/bookings/:customer_booking_id/cancel_by_customer", "language": "curl" } ] } [/block] After the customer has cancelled the booking, a notification is sent to the owner via email.
{"_id":"582b2e204c28ec2700ae86c7","body":"With the `instant_payment` graph, you can collect payments from customers as they sign up for a booking. You can use whichever method you prefer to collect the payments. After collecting a payment for a booking, you simply need to make Timekit aware that a customer has paid and the booking will enter a paid state.\n\n* [A blueprint for paid bookings](http://developers.timekit.io/v2/docs/payments#a-blueprint-for-paid-bookings)\n* [Creating a booking](http://developers.timekit.io/v2/docs/payments#creating-a-booking)\n* [Paying for a booking](http://developers.timekit.io/v2/docs/payments#paying-for-a-booking)\n* [Timing out payments](http://developers.timekit.io/v2/docs/payments#timing-out-payments)\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"A blueprint for paid bookings\"\n}\n[/block]\nThe `instant_payment` graph is a blueprint for handling payments in your booking flow. It looks like this:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/01fefcf-instant_payment_graph.png\",\n        \"instant_payment_graph.png\",\n        592,\n        1808,\n        \"#e3ebeb\"\n      ],\n      \"caption\": \"The `instant_payment` graph.\"\n    }\n  ]\n}\n[/block]\nThere are a few ways in which the `instant_payment` graph differs from the `instant` graph. First of all, where the `instant` graph goes directly into a `confirmed` state, the `instant_payment` graph goes into a `tentative` state. Before entering this state, a timeout is set (the default is 5 minutes) after which the booking will automatically enter an `unpaid` state. While the booking is in its `tentative` state, you can mark it as paid, which, of course, will move it into a `paid` state. The `paid` state is similar to the `confirmed` state that non-payment booking flows have.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Creating a booking\"\n}\n[/block]\nCreating a booking using the `instant_payment` graph is similar to creating any other 1-on-1 booking. This is an example JSON payload you would [POST] to [/bookings](doc:bookings):\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"graph\\\": \\\"instant_payment\\\",\\n  \\\"action\\\": \\\"create\\\",\\n  \\\"event\\\": {\\n    \\\"start\\\": \\\"2015-03-01T08:00:00+00:00\\\",\\n    \\\"end\\\": \\\"2015-03-01T13:00:00+00:00\\\",\\n    \\\"what\\\": \\\"Mens haircut\\\",\\n    \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n    \\\"calendar_id\\\": \\\"replace-with-id\\\",\\n    \\\"description\\\": \\\"Please arrive 10 minutes before you time begin\\\"\\n  },\\n  \\\"customer\\\": {\\n    \\\"name\\\": \\\"Marty McFly\\\",\\n    \\\"email\\\": \\\"marty.mcfly@timekit.io\\\",\\n    \\\"phone\\\": \\\"1-591-001-5403\\\",\\n    \\\"voip\\\": \\\"McFly\\\",\\n    \\\"timezone\\\": \\\"America/Los_Angeles\\\"\\n  }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nThe JSON response would look similar to this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"data\\\": {\\n    \\\"id\\\": \\\"58190fc6-1ec0-4ebb-b627-7ce6aa9fc703\\\",\\n    \\\"graph\\\": \\\"instant_payment\\\",\\n    \\\"state\\\": \\\"tentative\\\",\\n    \\\"completed\\\": false,\\n    \\\"created_at\\\": \\\"2016-02-11T11:58:45+0100\\\",\\n    \\\"updated_at\\\": \\\"2016-02-11T11:58:47+0100\\\",\\n    \\\"available_actions\\\": [\\n      \\\"pay\\\"\\n    ],\\n    \\\"attributes\\\": {\\n      \\\"event_info\\\": {\\n        \\\"start\\\": \\\"2015-03-01T08:00:00+00:00\\\",\\n        \\\"end\\\": \\\"2015-03-01T13:00:00+00:00\\\",\\n        \\\"what\\\": \\\"Mens haircut\\\",\\n        \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n        \\\"description\\\": \\\"Please arrive 10 minutes before you time begin\\\"\\n      }\\n    },\\n    \\\"calendar\\\": {\\n      \\\"id\\\": \\\"c91c5d04-2a57-46c0-ab35-e489dadf132e\\\",\\n      \\\"name\\\": \\\"My calendar\\\",\\n      \\\"display_name\\\": \\\"My calendar\\\",\\n      \\\"description\\\": \\\"Ut adipisci non autem cum ut id.\\\",\\n      \\\"foregroundcolor\\\": \\\"#25d6be\\\",\\n      \\\"backgroundcolor\\\": \\\"#ea1cb8\\\",\\n      \\\"created_at\\\": \\\"2016-02-15T13:21:42+0100\\\",\\n      \\\"updated_at\\\": \\\"2016-02-15T13:21:42+0100\\\"\\n    },\\n    \\\"customers\\\": [\\n      {\\n        \\\"id\\\": \\\"a728e860-99c7-4009-8843-7d9ac5d7f53f\\\",\\n        \\\"name\\\": \\\"Marty McFly\\\",\\n        \\\"email\\\": \\\"marty.mcfly@timekit.io\\\",\\n        \\\"phone\\\": \\\"1-591-001-5403\\\",\\n        \\\"voip\\\": \\\"McFly\\\",\\n        \\\"timezone\\\": \\\"America/Los_Angeles\\\"\\n      }\\n    ]\\n  }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nNow, the booking is in a `tentative` state and will time out in 5 minutes, unless you mark it as `paid`.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Paying for a booking\"\n}\n[/block]\nAlthough Timekit offers a blueprint for your paid booking flows, and is aware if a booking has been paid or not, you need to handle the actual payment on your end. Timekit is 100% flexible in the sense that you can use whichever method you prefer to handle your payments.\n\nWhen you transition a booking into a `paid` state, you need to provide a `payment_id`. This can really be anything that helps you identify the payment, but usually it would be something like a Stripe transaction ID.\n\nHere's the JSON you would [PUT] to the [/bookings/:id/:action](doc:bookingsidaction) endpoint in order to transition a booking into a `paid` state:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"pay\\\": {\\n    \\\"payment_id\\\": \\\"ch_191szuINaMd4BFD1REo9yJaF\\\"\\n  }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nThe booking will now enter its `paid` state, which is similar to the `confirmed` state in a booking following the `instant` (non-payment) graph.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Timing out payments\"\n}\n[/block]\nOnce a booking has entered a `tentative` state, by default, it will time out in 5 minutes and transition into an `unpaid` state. You can set the value of the timeout yourself, when you create the booking. Here's an example of how the JSON in a [POST] request to the [/bookings](doc:bookings) endpoint would look:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"graph\\\": \\\"instant_payment\\\",\\n  \\\"action\\\": \\\"create\\\",\\n  \\\"event\\\": {\\n    \\\"start\\\": \\\"2015-03-01T08:00:00+00:00\\\",\\n    \\\"end\\\": \\\"2015-03-01T13:00:00+00:00\\\",\\n    \\\"what\\\": \\\"Mens haircut\\\",\\n    \\\"where\\\": \\\"Sesame St, Middleburg, FL 32068, USA\\\",\\n    \\\"calendar_id\\\": \\\"replace-with-id\\\",\\n    \\\"description\\\": \\\"Please arrive 10 minutes before you time begin\\\"\\n  },\\n  \\\"customer\\\": {\\n    \\\"name\\\": \\\"Marty McFly\\\",\\n    \\\"email\\\": \\\"marty.mcfly@timekit.io\\\",\\n    \\\"phone\\\": \\\"1-591-001-5403\\\",\\n    \\\"voip\\\": \\\"McFly\\\",\\n    \\\"timezone\\\": \\\"America/Los_Angeles\\\"\\n  },\\n  \\\"timeout\\\": {\\n  \\t\\\"unit\\\": \\\"sec\\\",\\n    \\\"time\\\": 60\\n  }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nThis will set the timeout to 60 seconds. You can also use `min` as your unit.\n\nThat's it! If you have any questions about how to incorporate payments into your booking flow, hit us up on the chat.\n\nWe recommend that you also take a look at our guide \"[Building booking experiences with Timekit](doc:building-booking-experiences-with-timekit)\".","excerpt":"Are you collecting payments as part of your booking flow?","link_url":"","type":"basic","updates":[],"version":"550bfb5522ccb01700a79469","__v":0,"category":"56c6d51cfd00bb0d0016dac5","githubsync":"","sync_unique":"","api":{"results":{"codes":[{"language":"json","code":"{}","name":"","status":200},{"code":"{}","name":"","status":400,"language":"json"}]},"settings":"","auth":"required","params":[],"url":""},"isReference":true,"next":{"pages":[],"description":""},"project":"550ada512188a71900453199","title":"Payments","createdAt":"2016-11-15T15:47:44.087Z","hidden":false,"link_external":false,"order":11,"parentDoc":null,"slug":"payments","user":"57c7e8a25754fa1700b121df","childrenPages":[]}

Payments

Are you collecting payments as part of your booking flow?

With the `instant_payment` graph, you can collect payments from customers as they sign up for a booking. You can use whichever method you prefer to collect the payments. After collecting a payment for a booking, you simply need to make Timekit aware that a customer has paid and the booking will enter a paid state. * [A blueprint for paid bookings](http://developers.timekit.io/v2/docs/payments#a-blueprint-for-paid-bookings) * [Creating a booking](http://developers.timekit.io/v2/docs/payments#creating-a-booking) * [Paying for a booking](http://developers.timekit.io/v2/docs/payments#paying-for-a-booking) * [Timing out payments](http://developers.timekit.io/v2/docs/payments#timing-out-payments) [block:api-header] { "type": "basic", "title": "A blueprint for paid bookings" } [/block] The `instant_payment` graph is a blueprint for handling payments in your booking flow. It looks like this: [block:image] { "images": [ { "image": [ "https://files.readme.io/01fefcf-instant_payment_graph.png", "instant_payment_graph.png", 592, 1808, "#e3ebeb" ], "caption": "The `instant_payment` graph." } ] } [/block] There are a few ways in which the `instant_payment` graph differs from the `instant` graph. First of all, where the `instant` graph goes directly into a `confirmed` state, the `instant_payment` graph goes into a `tentative` state. Before entering this state, a timeout is set (the default is 5 minutes) after which the booking will automatically enter an `unpaid` state. While the booking is in its `tentative` state, you can mark it as paid, which, of course, will move it into a `paid` state. The `paid` state is similar to the `confirmed` state that non-payment booking flows have. [block:api-header] { "type": "basic", "title": "Creating a booking" } [/block] Creating a booking using the `instant_payment` graph is similar to creating any other 1-on-1 booking. This is an example JSON payload you would [POST] to [/bookings](doc:bookings): [block:code] { "codes": [ { "code": "{\n \"graph\": \"instant_payment\",\n \"action\": \"create\",\n \"event\": {\n \"start\": \"2015-03-01T08:00:00+00:00\",\n \"end\": \"2015-03-01T13:00:00+00:00\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \"replace-with-id\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n },\n \"customer\": {\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n}", "language": "json" } ] } [/block] The JSON response would look similar to this: [block:code] { "codes": [ { "code": "{\n \"data\": {\n \"id\": \"58190fc6-1ec0-4ebb-b627-7ce6aa9fc703\",\n \"graph\": \"instant_payment\",\n \"state\": \"tentative\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T11:58:45+0100\",\n \"updated_at\": \"2016-02-11T11:58:47+0100\",\n \"available_actions\": [\n \"pay\"\n ],\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2015-03-01T08:00:00+00:00\",\n \"end\": \"2015-03-01T13:00:00+00:00\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n }\n },\n \"calendar\": {\n \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n \"name\": \"My calendar\",\n \"display_name\": \"My calendar\",\n \"description\": \"Ut adipisci non autem cum ut id.\",\n \"foregroundcolor\": \"#25d6be\",\n \"backgroundcolor\": \"#ea1cb8\",\n \"created_at\": \"2016-02-15T13:21:42+0100\",\n \"updated_at\": \"2016-02-15T13:21:42+0100\"\n },\n \"customers\": [\n {\n \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n ]\n }\n}", "language": "json" } ] } [/block] Now, the booking is in a `tentative` state and will time out in 5 minutes, unless you mark it as `paid`. [block:api-header] { "type": "basic", "title": "Paying for a booking" } [/block] Although Timekit offers a blueprint for your paid booking flows, and is aware if a booking has been paid or not, you need to handle the actual payment on your end. Timekit is 100% flexible in the sense that you can use whichever method you prefer to handle your payments. When you transition a booking into a `paid` state, you need to provide a `payment_id`. This can really be anything that helps you identify the payment, but usually it would be something like a Stripe transaction ID. Here's the JSON you would [PUT] to the [/bookings/:id/:action](doc:bookingsidaction) endpoint in order to transition a booking into a `paid` state: [block:code] { "codes": [ { "code": "{\n \"pay\": {\n \"payment_id\": \"ch_191szuINaMd4BFD1REo9yJaF\"\n }\n}", "language": "json" } ] } [/block] The booking will now enter its `paid` state, which is similar to the `confirmed` state in a booking following the `instant` (non-payment) graph. [block:api-header] { "type": "basic", "title": "Timing out payments" } [/block] Once a booking has entered a `tentative` state, by default, it will time out in 5 minutes and transition into an `unpaid` state. You can set the value of the timeout yourself, when you create the booking. Here's an example of how the JSON in a [POST] request to the [/bookings](doc:bookings) endpoint would look: [block:code] { "codes": [ { "code": "{\n \"graph\": \"instant_payment\",\n \"action\": \"create\",\n \"event\": {\n \"start\": \"2015-03-01T08:00:00+00:00\",\n \"end\": \"2015-03-01T13:00:00+00:00\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \"replace-with-id\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n },\n \"customer\": {\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n },\n \"timeout\": {\n \t\"unit\": \"sec\",\n \"time\": 60\n }\n}", "language": "json" } ] } [/block] This will set the timeout to 60 seconds. You can also use `min` as your unit. That's it! If you have any questions about how to incorporate payments into your booking flow, hit us up on the chat. We recommend that you also take a look at our guide "[Building booking experiences with Timekit](doc:building-booking-experiences-with-timekit)".
With the `instant_payment` graph, you can collect payments from customers as they sign up for a booking. You can use whichever method you prefer to collect the payments. After collecting a payment for a booking, you simply need to make Timekit aware that a customer has paid and the booking will enter a paid state. * [A blueprint for paid bookings](http://developers.timekit.io/v2/docs/payments#a-blueprint-for-paid-bookings) * [Creating a booking](http://developers.timekit.io/v2/docs/payments#creating-a-booking) * [Paying for a booking](http://developers.timekit.io/v2/docs/payments#paying-for-a-booking) * [Timing out payments](http://developers.timekit.io/v2/docs/payments#timing-out-payments) [block:api-header] { "type": "basic", "title": "A blueprint for paid bookings" } [/block] The `instant_payment` graph is a blueprint for handling payments in your booking flow. It looks like this: [block:image] { "images": [ { "image": [ "https://files.readme.io/01fefcf-instant_payment_graph.png", "instant_payment_graph.png", 592, 1808, "#e3ebeb" ], "caption": "The `instant_payment` graph." } ] } [/block] There are a few ways in which the `instant_payment` graph differs from the `instant` graph. First of all, where the `instant` graph goes directly into a `confirmed` state, the `instant_payment` graph goes into a `tentative` state. Before entering this state, a timeout is set (the default is 5 minutes) after which the booking will automatically enter an `unpaid` state. While the booking is in its `tentative` state, you can mark it as paid, which, of course, will move it into a `paid` state. The `paid` state is similar to the `confirmed` state that non-payment booking flows have. [block:api-header] { "type": "basic", "title": "Creating a booking" } [/block] Creating a booking using the `instant_payment` graph is similar to creating any other 1-on-1 booking. This is an example JSON payload you would [POST] to [/bookings](doc:bookings): [block:code] { "codes": [ { "code": "{\n \"graph\": \"instant_payment\",\n \"action\": \"create\",\n \"event\": {\n \"start\": \"2015-03-01T08:00:00+00:00\",\n \"end\": \"2015-03-01T13:00:00+00:00\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \"replace-with-id\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n },\n \"customer\": {\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n}", "language": "json" } ] } [/block] The JSON response would look similar to this: [block:code] { "codes": [ { "code": "{\n \"data\": {\n \"id\": \"58190fc6-1ec0-4ebb-b627-7ce6aa9fc703\",\n \"graph\": \"instant_payment\",\n \"state\": \"tentative\",\n \"completed\": false,\n \"created_at\": \"2016-02-11T11:58:45+0100\",\n \"updated_at\": \"2016-02-11T11:58:47+0100\",\n \"available_actions\": [\n \"pay\"\n ],\n \"attributes\": {\n \"event_info\": {\n \"start\": \"2015-03-01T08:00:00+00:00\",\n \"end\": \"2015-03-01T13:00:00+00:00\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n }\n },\n \"calendar\": {\n \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n \"name\": \"My calendar\",\n \"display_name\": \"My calendar\",\n \"description\": \"Ut adipisci non autem cum ut id.\",\n \"foregroundcolor\": \"#25d6be\",\n \"backgroundcolor\": \"#ea1cb8\",\n \"created_at\": \"2016-02-15T13:21:42+0100\",\n \"updated_at\": \"2016-02-15T13:21:42+0100\"\n },\n \"customers\": [\n {\n \"id\": \"a728e860-99c7-4009-8843-7d9ac5d7f53f\",\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n }\n ]\n }\n}", "language": "json" } ] } [/block] Now, the booking is in a `tentative` state and will time out in 5 minutes, unless you mark it as `paid`. [block:api-header] { "type": "basic", "title": "Paying for a booking" } [/block] Although Timekit offers a blueprint for your paid booking flows, and is aware if a booking has been paid or not, you need to handle the actual payment on your end. Timekit is 100% flexible in the sense that you can use whichever method you prefer to handle your payments. When you transition a booking into a `paid` state, you need to provide a `payment_id`. This can really be anything that helps you identify the payment, but usually it would be something like a Stripe transaction ID. Here's the JSON you would [PUT] to the [/bookings/:id/:action](doc:bookingsidaction) endpoint in order to transition a booking into a `paid` state: [block:code] { "codes": [ { "code": "{\n \"pay\": {\n \"payment_id\": \"ch_191szuINaMd4BFD1REo9yJaF\"\n }\n}", "language": "json" } ] } [/block] The booking will now enter its `paid` state, which is similar to the `confirmed` state in a booking following the `instant` (non-payment) graph. [block:api-header] { "type": "basic", "title": "Timing out payments" } [/block] Once a booking has entered a `tentative` state, by default, it will time out in 5 minutes and transition into an `unpaid` state. You can set the value of the timeout yourself, when you create the booking. Here's an example of how the JSON in a [POST] request to the [/bookings](doc:bookings) endpoint would look: [block:code] { "codes": [ { "code": "{\n \"graph\": \"instant_payment\",\n \"action\": \"create\",\n \"event\": {\n \"start\": \"2015-03-01T08:00:00+00:00\",\n \"end\": \"2015-03-01T13:00:00+00:00\",\n \"what\": \"Mens haircut\",\n \"where\": \"Sesame St, Middleburg, FL 32068, USA\",\n \"calendar_id\": \"replace-with-id\",\n \"description\": \"Please arrive 10 minutes before you time begin\"\n },\n \"customer\": {\n \"name\": \"Marty McFly\",\n \"email\": \"marty.mcfly@timekit.io\",\n \"phone\": \"1-591-001-5403\",\n \"voip\": \"McFly\",\n \"timezone\": \"America/Los_Angeles\"\n },\n \"timeout\": {\n \t\"unit\": \"sec\",\n \"time\": 60\n }\n}", "language": "json" } ] } [/block] This will set the timeout to 60 seconds. You can also use `min` as your unit. That's it! If you have any questions about how to incorporate payments into your booking flow, hit us up on the chat. We recommend that you also take a look at our guide "[Building booking experiences with Timekit](doc:building-booking-experiences-with-timekit)".
{"_id":"55ce707a950b8e0d00f11f96","createdAt":"2015-08-14T22:49:30.497Z","updates":[],"__v":1,"body":"You can create a new calendar for the current user by calling this endpoint.\n\nIf the user/resource has a connected Google account, then we will save the new calendar to Google. \nTo get the calendar synced you need to use the [[PUT] /calendars/:id](doc:calendarsid-2) endpoint to set the `provider_sync` flag to true.","hidden":false,"isReference":true,"link_url":"","slug":"calendars-1","sync_unique":"","type":"post","api":{"url":"/calendars","auth":"required","examples":{"codes":[{"language":"json","code":"{\n    \"name\": \"Important encounters with Marty\",\n    \"description\": \"Througout time, Marty and I really need to meet in order for the world not to collapse into Biffy cazyness\",\n    \"foregroundcolor\": \"#000000\",\n    \"backgroundcolor\": \"#FFFFFF\"\n}","name":""},{"code":"curl -X POST \\\n  -H 'Timekit-App: back-to-the-future' \\\n  -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW\\\n  -d '{\n    \"name\": \"Important encounters with Marty\",\n    \"description\": \"Througout time, Marty and I really need to meet in order for the world not to collapse into Biffy cazyness\",\n    \"foregroundcolor\": \"#000000\",\n    \"backgroundcolor\": \"#FFFFFF\"\n\t}' \\\n  https://api.timekit.io/v2/calendars ","language":"curl"}]},"method":"post","params":[{"required":true,"type":"string","in":"body","_id":"55ce707a950b8e0d00f11f9a","default":"","desc":"Name of the calendar","name":"name","ref":""},{"required":true,"type":"string","in":"body","_id":"55ce707a950b8e0d00f11f99","default":"","desc":"Description of the calendar","name":"description","ref":""},{"required":false,"type":"string","in":"body","_id":"55ce707a950b8e0d00f11f98","default":"","desc":"Hex color to use as background color for events in this calendar","name":"backgroundcolor","ref":""},{"desc":"Hex color to use as foreground color for events in this calendar","name":"foregroundcolor","ref":"","required":false,"type":"string","in":"body","_id":"55ce707a950b8e0d00f11f97","default":""}],"results":{"codes":[{"language":"json","code":"{\n  \"data\": {\n    \"id\": \"bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2\",\n    \"name\": \"Important encounters with Marty\",\n    \"description\": \"Througout time, Marty and I really need to meet in order for the world not to collapse into Biffy cazyness\",\n    \"foregroundcolor\": \"#000000\",\n    \"backgroundcolor\": \"#FFFFFF\",\n    \"provider_id\": \"my-calendar\",\n    \"provider_access\": \"owner\",\n    \"provider_primary\": false,\n    \"provider_sync\": false,\n    \"created_at\": \"2016-02-29T18:41:38+0100\",\n    \"updated_at\": \"2016-06-02T23:00:03+0200\"  }\n}","name":"","status":201},{"status":400,"language":"json","code":"{}","name":""}]},"settings":""},"category":"551138679171e82b00897150","githubsync":"","next":{"description":"","pages":[]},"title":"/calendars","user":"550ada38cd78a42300ddf508","editedParams2":true,"excerpt":"Create calendar","link_external":false,"order":0,"parentDoc":null,"project":"550ada512188a71900453199","version":"550bfb5522ccb01700a79469","editedParams":true,"childrenPages":[]}

post/calendars

Create calendar

Body Params

name:
required
string
Name of the calendar
description:
required
string
Description of the calendar
backgroundcolor:
string
Hex color to use as background color for events in this calendar
foregroundcolor:
string
Hex color to use as foreground color for events in this calendar
You can create a new calendar for the current user by calling this endpoint. If the user/resource has a connected Google account, then we will save the new calendar to Google. To get the calendar synced you need to use the [[PUT] /calendars/:id](doc:calendarsid-2) endpoint to set the `provider_sync` flag to true.

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



You can create a new calendar for the current user by calling this endpoint. If the user/resource has a connected Google account, then we will save the new calendar to Google. To get the calendar synced you need to use the [[PUT] /calendars/:id](doc:calendarsid-2) endpoint to set the `provider_sync` flag to true.
{"_id":"551138df0c1a08190077f6ad","sync_unique":"","githubsync":"","link_external":false,"link_url":"","slug":"calendars","isReference":true,"next":{"description":"","pages":[]},"title":"/calendars","updates":[],"__v":13,"category":"551138679171e82b00897150","excerpt":"List calendars","hidden":false,"user":"550ada38cd78a42300ddf508","version":"550bfb5522ccb01700a79469","body":"Retrieve a list of the resource's calendars. \n\nIf your user/resource is connected to Google, the calendars returned will be your Google calendars. The `provider_*` fields are specific to Google calendars only and are synced from Google. \n\nTo choose which calendars that should be synced from Google, see the [[PUT] /calendars:/:id](doc:calendarsid-2) endpoint.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Google calendars missing\",\n  \"body\": \"If some Google calendars are not showing, you can trigger a sync manually, which will fetch and update all calendars from Google.\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Dynamically include events\",\n  \"body\": \"You can fetch all events grouped per calendar by setting the [dynamic include](doc:dynamic-includes) parameter: ?include=events\"\n}\n[/block]","createdAt":"2015-03-24T10:13:51.915Z","order":1,"parentDoc":null,"api":{"auth":"required","examples":{"codes":[{"language":"curl","code":"curl -X GET \\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n     https://api.timekit.io/v2/calendars"}]},"method":"get","params":[],"results":{"codes":[{"name":"","code":"{\n  \"data\": [\n    {\n      \"id\": \"bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2\",\n      \"name\": \"Important encounters with Marty\",\n      \"display_name\": \"Important encounters with Marty\",\n      \"description\": \"Througout time, Marty and I really need to meet in order for the world not to collapse into Biffy cazyness.\",\n      \"foregroundcolor\": \"#000000\",\n      \"backgroundcolor\": \"#FFFFFF\",\n      \"provider_id\": \"important-encounters-with-marty\",\n      \"provider_access\": \"reader\",\n      \"provider_primary\": false,\n      \"provider_sync\": false,\n      \"created_at\": \"2016-02-29T18:41:38+0100\",\n      \"updated_at\": \"2016-06-02T23:00:03+0200\"\n    },\n    {\n      \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n      \"name\": \"My personal calendar\",\n      \"display_name\": \"My personal calendar\",\n      \"description\": \"Notes to self, so I don't remember to to them.\",\n      \"foregroundcolor\": \"#25d6be\",\n      \"backgroundcolor\": \"#ea1cb8\",\n      \"provider_id\": \"my-personal-google-calendar\",\n      \"provider_access\": \"owner\",\n      \"provider_primary\": true,\n      \"provider_sync\": true,\n      \"created_at\": \"2016-02-29T18:41:38+0100\",\n      \"updated_at\": \"2016-06-02T23:00:03+0200\"\n    }\n  ]\n}","language":"json","status":200},{"name":"","code":"Invalid credentials.","language":"text","status":401}]},"settings":"","url":"/calendars"},"project":"550ada512188a71900453199","type":"get","childrenPages":[]}

get/calendars

List calendars

Retrieve a list of the resource's calendars. If your user/resource is connected to Google, the calendars returned will be your Google calendars. The `provider_*` fields are specific to Google calendars only and are synced from Google. To choose which calendars that should be synced from Google, see the [[PUT] /calendars:/:id](doc:calendarsid-2) endpoint. [block:callout] { "type": "warning", "title": "Google calendars missing", "body": "If some Google calendars are not showing, you can trigger a sync manually, which will fetch and update all calendars from Google." } [/block] [block:callout] { "type": "success", "title": "Dynamically include events", "body": "You can fetch all events grouped per calendar by setting the [dynamic include](doc:dynamic-includes) parameter: ?include=events" } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



Retrieve a list of the resource's calendars. If your user/resource is connected to Google, the calendars returned will be your Google calendars. The `provider_*` fields are specific to Google calendars only and are synced from Google. To choose which calendars that should be synced from Google, see the [[PUT] /calendars:/:id](doc:calendarsid-2) endpoint. [block:callout] { "type": "warning", "title": "Google calendars missing", "body": "If some Google calendars are not showing, you can trigger a sync manually, which will fetch and update all calendars from Google." } [/block] [block:callout] { "type": "success", "title": "Dynamically include events", "body": "You can fetch all events grouped per calendar by setting the [dynamic include](doc:dynamic-includes) parameter: ?include=events" } [/block]
{"_id":"5511391fa226890d0091164d","version":"550bfb5522ccb01700a79469","api":{"auth":"required","examples":{"codes":[{"language":"curl","code":"curl -X GET \\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n     https://api.timekit.io/v2/calendars/c91c5d04-2a57-46c0-ab35-e489dadf132e"}]},"method":"get","params":[{"default":"","desc":"Id of the calendar","name":"id","ref":"","required":true,"type":"string","in":"path","_id":"551139cc9171e82b00897158"}],"results":{"codes":[{"name":"","code":"{\n  \"data\": {\n    \"id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n    \"name\": \"My personal calendar\",\n    \"display_name\": \"My personal calendar\",\n    \"description\": \"Notes to self, so I don't remember to to them.\",\n    \"foregroundcolor\": \"#25d6be\",\n    \"backgroundcolor\": \"#ea1cb8\",\n    \"provider_id\": \"my-personal-google-calendar\",\n    \"provider_access\": \"owner\",\n    \"provider_primary\": true,\n    \"provider_sync\": true,\n    \"created_at\": \"2016-02-29T18:41:38+0100\",\n    \"updated_at\": \"2016-06-02T23:00:03+0200\"\n  }\n}","language":"json","status":200},{"name":"","code":"Invalid credentials.","language":"text","status":401},{"status":404,"code":"{\n  \"error\": {\n    \"message\": \"Resource Not Found\",\n    \"status_code\": 404\n  }\n}","language":"json"}]},"settings":"","url":"/calendars/:id"},"isReference":true,"link_external":false,"link_url":"","sync_unique":"","title":"/calendars/:id","type":"get","createdAt":"2015-03-24T10:14:55.928Z","excerpt":"","githubsync":"","next":{"description":"","pages":[]},"project":"550ada512188a71900453199","slug":"calendarsid","body":"Retrieve a specific calendar.","category":"551138679171e82b00897150","hidden":false,"order":2,"parentDoc":null,"__v":2,"editedParams":true,"editedParams2":true,"updates":[],"user":"550ada38cd78a42300ddf508","childrenPages":[]}

get/calendars/:id


Path Params

id:
required
string
Id of the calendar
Retrieve a specific calendar.

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



Retrieve a specific calendar.
{"_id":"5750a6af51b4bb2b001786ed","category":"551138679171e82b00897150","order":3,"parentDoc":null,"type":"put","body":"Google-connected calendars can be set to either sync or not sync. \n\nIf you set `provider_sync: false`, then all events in Timekit attached to the calendar will be flushed (but will remain in Google) and the calendar will not be automatically synced in the future. \n\nIf you set `provider_sync: true`, then the calendar will be automatically synced in the future. Please call [[GET] /accounts/sync](doc:accountssync) at least once afterwards to make sure that all events gets fetched from Google initially.\n\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"Updating name, description and other calendar properties are currently not possible.\"\n}\n[/block]","createdAt":"2016-06-02T21:35:43.811Z","excerpt":"","link_url":"","next":{"description":"","pages":[]},"user":"550bf7b2eb24860d00e6a33b","title":"/calendars/:id","updates":[],"editedParams":true,"githubsync":"","isReference":true,"link_external":false,"project":"550ada512188a71900453199","slug":"calendarsid-2","version":"550bfb5522ccb01700a79469","__v":1,"api":{"examples":{"codes":[{"language":"json","code":"{\n  \"provider_sync\": true\n}"},{"language":"curl","code":"curl -X PUT \\\n  -H 'Timekit-App: back-to-the-future' \\\n  -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n  -d '{\"provider_sync\": true}' \\\n  https://api.timekit.io/v2/calendars/bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2 "}]},"method":"put","params":[{"_id":"5750a6af51b4bb2b001786ee","default":"","desc":"ID of the calendar you want to update","name":"id","ref":"","required":true,"type":"string","in":"path"}],"results":{"codes":[{"language":"json","code":"","name":"","status":204},{"code":"{}","name":"","status":400,"language":"json"}]},"settings":"","url":"/calendars/:id","auth":"required"},"editedParams2":true,"hidden":false,"sync_unique":"","childrenPages":[]}

put/calendars/:id


Path Params

id:
required
string
ID of the calendar you want to update
Google-connected calendars can be set to either sync or not sync. If you set `provider_sync: false`, then all events in Timekit attached to the calendar will be flushed (but will remain in Google) and the calendar will not be automatically synced in the future. If you set `provider_sync: true`, then the calendar will be automatically synced in the future. Please call [[GET] /accounts/sync](doc:accountssync) at least once afterwards to make sure that all events gets fetched from Google initially. [block:callout] { "type": "warning", "body": "Updating name, description and other calendar properties are currently not possible." } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples



Google-connected calendars can be set to either sync or not sync. If you set `provider_sync: false`, then all events in Timekit attached to the calendar will be flushed (but will remain in Google) and the calendar will not be automatically synced in the future. If you set `provider_sync: true`, then the calendar will be automatically synced in the future. Please call [[GET] /accounts/sync](doc:accountssync) at least once afterwards to make sure that all events gets fetched from Google initially. [block:callout] { "type": "warning", "body": "Updating name, description and other calendar properties are currently not possible." } [/block]
{"_id":"55f720afe9a0860d009e9ad7","category":"551138679171e82b00897150","order":4,"title":"/calendars/:id","body":"You can delete a calendar on the Timekit platform by using this endpoint. You can delete any calendar if the resource doesn't have a connected google account\n\nIf the user/resource has a connected Google account, you can only delete calendars that have been created using the [[POST] /calendars](doc:calendars-1) endpoint. This is to avoid private calendars are deleted in error (or abused) without consent of the Google account owner.","editedParams":true,"editedParams2":true,"githubsync":"","updates":[],"user":"550ada38cd78a42300ddf508","__v":1,"link_external":false,"link_url":"","slug":"calendarsid-1","type":"delete","version":"550bfb5522ccb01700a79469","hidden":false,"api":{"examples":{"codes":[]},"method":"delete","params":[{"required":true,"type":"string","in":"path","_id":"55f720afe9a0860d009e9ad8","default":"","desc":"The ID of the calendar","name":"id","ref":""}],"results":{"codes":[{"status":204,"language":"json","code":" ","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/calendars/:id","auth":"required"},"createdAt":"2015-09-14T19:31:59.488Z","excerpt":"","isReference":true,"parentDoc":null,"project":"550ada512188a71900453199","sync_unique":"","next":{"description":"","pages":[]},"childrenPages":[]}

delete/calendars/:id


Path Params

id:
required
string
The ID of the calendar
You can delete a calendar on the Timekit platform by using this endpoint. You can delete any calendar if the resource doesn't have a connected google account If the user/resource has a connected Google account, you can only delete calendars that have been created using the [[POST] /calendars](doc:calendars-1) endpoint. This is to avoid private calendars are deleted in error (or abused) without consent of the Google account owner.

Definition

{{ api_url }}{{ page_api_url }}

Result Format



You can delete a calendar on the Timekit platform by using this endpoint. You can delete any calendar if the resource doesn't have a connected google account If the user/resource has a connected Google account, you can only delete calendars that have been created using the [[POST] /calendars](doc:calendars-1) endpoint. This is to avoid private calendars are deleted in error (or abused) without consent of the Google account owner.
{"_id":"5655bbf054ae2c0d004f4de7","type":"get","updates":[],"user":"550ada38cd78a42300ddf508","category":"5655bbc954ae2c0d004f4de4","excerpt":"","order":0,"project":"550ada512188a71900453199","title":"/credentials","version":"550bfb5522ccb01700a79469","createdAt":"2015-11-25T13:47:28.585Z","isReference":true,"sync_unique":"","api":{"method":"get","params":[],"results":{"codes":[{"language":"json","code":"{\n  \"data\": [\n    {\n      \"id\": \"d293de32-5afd-4d03-8c45-a0dec5fab3eb\",\n      \"type\": \"server-token\",\n      \"description\": \"Token generated on resource creation\",\n      \"token\": \"dasddaHJKLASDKJHA7640SDnnnndaaa\",\n      \"scopes\": [\n        \"global\"\n      ],\n      \"token_generated_at\": \"2015-11-06T12:22:04+00:00\"\n    },\n    {\n      \"id\": \"961306f8-b038-419d-4f21-443c4851e8a1\",\n      \"type\": \"client-token\",\n      \"description\": \"Booking.js embed access\",\n      \"token\": \"375w85a2Y6XqEPshc1laxDdQQsVg8pn0j\",\n      \"scopes\": [\n        \"widget\"\n      ],\n      \"token_generated_at\": \"2015-11-09T13:49:47+00:00\"\n    }\n ]\n}","name":"","status":200},{"code":"{}","name":"","status":400,"language":"json"}]},"settings":"","url":"/credentials","auth":"required","examples":{"codes":[]}},"body":"This endpoint lists your generated credentials (resource API tokens)","link_url":"","parentDoc":null,"__v":6,"githubsync":"","hidden":false,"link_external":false,"slug":"crendentials","next":{"description":"","pages":[]},"childrenPages":[]}

get/credentials


This endpoint lists your generated credentials (resource API tokens)

Definition

{{ api_url }}{{ page_api_url }}

Result Format



This endpoint lists your generated credentials (resource API tokens)
{"_id":"5655bfcfe0d82b0d00ab5867","editedParams":true,"parentDoc":null,"type":"post","slug":"credentials","api":{"examples":{"codes":[]},"method":"post","params":[{"_id":"5655bfcfe0d82b0d00ab586a","ref":"","in":"body","required":true,"desc":"'client-token' or 'server-token'","default":"","type":"string","name":"type"},{"_id":"5655bfcfe0d82b0d00ab586c","ref":"","in":"body","required":true,"desc":"'global' or 'widget'","default":"","type":"string","name":"scopes"},{"_id":"5655bfcfe0d82b0d00ab586b","ref":"","in":"body","required":true,"desc":"Description of these credentials","default":"","type":"string","name":"description"}],"results":{"codes":[{"status":200,"language":"json","code":"{\n  \"data\": {\n    \"id\": \"6211bdfb-3e6b-4b5c-b2b2-0a5ee3c3c746\",\n    \"type\": \"client-token\",\n    \"description\": \"BookingJS token\",\n    \"token\": \"CPDqMLOoT4quO7j71jfcD9VlYpJBDPqI\",\n    \"scopes\": [\n      \"widget\"\n    ],\n    \"token_generated_at\": \"2015-11-25T14:02:48+00:00\"\n  }\n}","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/credentials","auth":"required"},"editedParams2":true,"githubsync":"","link_external":false,"project":"550ada512188a71900453199","sync_unique":"","title":"/credentials","user":"550ada38cd78a42300ddf508","__v":2,"body":"Each resource gets a default pair of credentials (`server-token` type with `global` scope) when they are created (either by connecting with Google or as a plain resource). These give full access to the resource and if you're using API from your backend, you'll probably don't need to create more credentials.\n\n**Booking.js widget**\n\nIf you want to use the booking.js widget, which runs in the browser, you'll need an API token that only provides access to some of the endpoints. This ensures that visitors cannot impersonate the user/resource and make illegal changes to resource data and see personal information. \nThe widget only needs access to 3 endpoints:\n- [[POST] /findtime](doc:findtime)\n- [[POST] /bookings](doc:bookings-1)\n- [[GET] /resources/timezone/:email](doc:resourcestimezoneemail)\n\nTo create these credentials, please set the following parameters:\n- type: \"client-token\"\n- scopes: \"widget\"","hidden":false,"link_url":"","order":1,"version":"550bfb5522ccb01700a79469","updates":[],"category":"5655bbc954ae2c0d004f4de4","createdAt":"2015-11-25T14:03:59.536Z","excerpt":"","isReference":true,"next":{"description":"","pages":[]},"childrenPages":[]}

post/credentials


Body Params

type:
required
string
'client-token' or 'server-token'
scopes:
required
string
'global' or 'widget'
description:
required
string
Description of these credentials
Each resource gets a default pair of credentials (`server-token` type with `global` scope) when they are created (either by connecting with Google or as a plain resource). These give full access to the resource and if you're using API from your backend, you'll probably don't need to create more credentials. **Booking.js widget** If you want to use the booking.js widget, which runs in the browser, you'll need an API token that only provides access to some of the endpoints. This ensures that visitors cannot impersonate the user/resource and make illegal changes to resource data and see personal information. The widget only needs access to 3 endpoints: - [[POST] /findtime](doc:findtime) - [[POST] /bookings](doc:bookings-1) - [[GET] /resources/timezone/:email](doc:resourcestimezoneemail) To create these credentials, please set the following parameters: - type: "client-token" - scopes: "widget"

Definition

{{ api_url }}{{ page_api_url }}

Result Format



Each resource gets a default pair of credentials (`server-token` type with `global` scope) when they are created (either by connecting with Google or as a plain resource). These give full access to the resource and if you're using API from your backend, you'll probably don't need to create more credentials. **Booking.js widget** If you want to use the booking.js widget, which runs in the browser, you'll need an API token that only provides access to some of the endpoints. This ensures that visitors cannot impersonate the user/resource and make illegal changes to resource data and see personal information. The widget only needs access to 3 endpoints: - [[POST] /findtime](doc:findtime) - [[POST] /bookings](doc:bookings-1) - [[GET] /resources/timezone/:email](doc:resourcestimezoneemail) To create these credentials, please set the following parameters: - type: "client-token" - scopes: "widget"
{"_id":"5655bdf6dd82540d00278c29","title":"/credentials/:id","updates":[],"category":"5655bbc954ae2c0d004f4de4","editedParams2":true,"githubsync":"","link_external":false,"link_url":"","slug":"credentialsid","version":"550bfb5522ccb01700a79469","excerpt":"","isReference":true,"sync_unique":"","type":"delete","body":"Use this endpoint to delete any credentials, except for the credentials your are using now to perform the request.","hidden":false,"project":"550ada512188a71900453199","user":"550ada38cd78a42300ddf508","__v":0,"api":{"method":"delete","params":[{"default":"","type":"string","name":"id","in":"path","_id":"5655bdf6dd82540d00278c2a","required":false,"desc":"The uuid of the credentials you want to delete"}],"results":{"codes":[{"name":"","status":204,"language":"json","code":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/credentials/:id","auth":"required","examples":{"codes":[]}},"createdAt":"2015-11-25T13:56:06.192Z","editedParams":true,"order":2,"parentDoc":null,"childrenPages":[]}

delete/credentials/:id


Path Params

id:
string
The uuid of the credentials you want to delete
Use this endpoint to delete any credentials, except for the credentials your are using now to perform the request.

Definition

{{ api_url }}{{ page_api_url }}


Use this endpoint to delete any credentials, except for the credentials your are using now to perform the request.
{"_id":"551160626fccf32500018be7","type":"post","version":"550bfb5522ccb01700a79469","category":"55115f836fccf32500018be4","githubsync":"","link_url":"","project":"550ada512188a71900453199","slug":"findtime","title":"/findtime","updates":[],"api":{"method":"post","params":[{"desc":"Array of emails to check for mutual availability","default":"","type":"array_string","name":"emails","in":"body","_id":"551160626fccf32500018be9","ref":"","required":false},{"ref":"","required":false,"desc":"Array of uuid of resrouces to check for mutual availability","default":"","type":"array_string","name":"resource_ids","in":"body","_id":"5601ea921ba3720d00a6b962"},{"type":"array_string","name":"calendar_ids","in":"body","_id":"5601ea921ba3720d00a6b961","ref":"","required":false,"desc":"Array of uuid of calendars to check for mutual availability","default":""},{"type":"array_mixed","name":"filters","in":"body","_id":"5596b473430c481900db1bfc","ref":"","required":false,"desc":"Filters to apply, see filter reference page","default":""},{"required":false,"desc":"Reference a saved collection of filters","default":"","type":"string","name":"filtercollection_id","in":"body","_id":"56b9d88fb080c217005a98df","ref":""},{"desc":"When should we start looking for available time? Written is human language, eg. 1 day, tomorrow, 2 weeks","default":"","type":"string","name":"start","in":"body","_id":"56951b4bfcb1032d0089df7b","ref":"","required":false},{"ref":"","required":false,"desc":"How long into the future should we look for mutual availability (max 6 months)","default":"2 days","type":"string","name":"future","in":"body","_id":"551161309171e82b0089719e"},{"required":false,"desc":"How long should the availability be?","default":"1 hour","type":"string","name":"length","in":"body","_id":"551161309171e82b0089719d","ref":""},{"default":"desc","type":"string","name":"sort","in":"body","_id":"5596b58c46e90a0d00eb698f","ref":"","required":false,"desc":"Chronological ascending (asc) or desceding (desc) order of results"},{"_id":"564d9d751936752300aa642d","ref":"","required":false,"desc":"Do you want to ignore all day event in this query?","default":"false","type":"boolean","name":"ignore_all_day_events","in":"body"},{"_id":"575578e31df9420e00e02004","ref":"","required":false,"desc":"Return all overlapping timeslots? (see note)","default":"false","type":"boolean","name":"all_solutions","in":"body"}],"results":{"codes":[{"name":"","code":"{\n  \"data\": [\n    {\n      \"start\": \"2015-03-24 15:00:00\",\n      \"end\": \"2015-03-24 16:00:00\"\n    },\n    {\n      \"start\": \"2015-03-24 21:45:00\",\n      \"end\": \"2015-03-24 22:45:00\"\n    },\n    {\n      \"start\": \"2015-03-25 07:30:00\",\n      \"end\": \"2015-03-25 08:30:00\"\n    },\n    {\n      \"start\": \"2015-03-25 16:30:00\",\n      \"end\": \"2015-03-25 17:30:00\"\n    },\n    {\n      \"start\": \"2015-03-25 18:15:00\",\n      \"end\": \"2015-03-25 19:15:00\"\n    }\n  ]\n}","language":"json","status":200},{"name":"","code":"{\n  \"errors\": {\n    \"emails\": [\n      \"The emails field is required.\"\n    ]\n  }\n}","language":"json","status":422},{"language":"json","code":"{}","status":200}]},"settings":"","url":"/findtime","auth":"required","examples":{"codes":[{"code":"curl -X POST \\\n     -H 'Timekit-App: back-to-the-future' \\\n     -H 'Timekit-OutputTimestampFormat: Y-m-d H:i:s' \\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n     -d '{\n           \"emails\": [\n             \"doc.brown@timekit.io\",\n             \"marty.mcfly@timekit.io\"\n           ],\n\t\t\t\t\t \"filters\": {\n\t\t\t       \"or\": [\n      \t\t     { \"specific_day\": {\"day\": \"Monday\"} },\n\t\t           { \"specific_day_and_time\": {\"day\": \"Wednesday\", \"start\": 10, \"end\": 12, \"timezone\": \"Europe/Copenhagen\"} }\n             ],\n             \"and\": [\n\t\t           { \"business_hours\": {\"timezone\": \"America/Los_angeles\"} }\n             ]\n           },\n           \"future\": \"2 days\",\n           \"length\": \"30 minutes\"\n         }' \\\n     https://api.timekit.io/v2/findtime","language":"curl"}]}},"createdAt":"2015-03-24T13:02:26.398Z","editedParams":true,"next":{"description":"","pages":[]},"user":"550ada38cd78a42300ddf508","excerpt":"Look for mutual availability","hidden":false,"link_external":false,"order":0,"parentDoc":null,"sync_unique":"","__v":14,"body":"Makes it easy to find mutual availability across multiple resources. It will loop through all supplied resources and look for timeslots that are free for all resources.\n\nPlease see the [Filters Reference](/v2/docs/find-time-filters) page for description and examples of supported filters.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Future and length formats\",\n  \"body\": \"These can be written in \\\"natural language\\\" sentences, with an integer (e.g. 3) and a period (e.g. hours or weeks), like this: \\\"2 weeks\\\"\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"\\\"all_solutions\\\" option\",\n  \"body\": \"By default, the algorithm will return sequential available timeslots in the \\\"length\\\" duration you've specified. The available timeslots will not overlap, which means that some potential timeslots are ignored. If you want ALL timeslots (based on 15 minute intervals), then set \\\"all_solutions\\\" to true.\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"success\",\n  \"body\": \"If you want to conveniently re-use filters across requests, you can save filter collections using this [endpoint](/v2/docs/findtimefiltercollections)\",\n  \"title\": \"Filter collections\"\n}\n[/block]","editedParams2":true,"isReference":true,"childrenPages":[]}

post/findtime

Look for mutual availability

Body Params

emails:
array of strings
Array of emails to check for mutual availability
resource_ids:
array of strings
Array of uuid of resrouces to check for mutual availability
calendar_ids:
array of strings
Array of uuid of calendars to check for mutual availability
filters:
array of mixed
Filters to apply, see filter reference page
filtercollection_id:
string
Reference a saved collection of filters
start:
string
When should we start looking for available time? Written is human language, eg. 1 day, tomorrow, 2 weeks
future:
string2 days
How long into the future should we look for mutual availability (max 6 months)
length:
string1 hour
How long should the availability be?
sort:
stringdesc
Chronological ascending (asc) or desceding (desc) order of results
ignore_all_day_events:
booleanfalse
Do you want to ignore all day event in this query?
all_solutions:
booleanfalse
Return all overlapping timeslots? (see note)
Makes it easy to find mutual availability across multiple resources. It will loop through all supplied resources and look for timeslots that are free for all resources. Please see the [Filters Reference](/v2/docs/find-time-filters) page for description and examples of supported filters. [block:callout] { "type": "info", "title": "Future and length formats", "body": "These can be written in \"natural language\" sentences, with an integer (e.g. 3) and a period (e.g. hours or weeks), like this: \"2 weeks\"" } [/block] [block:callout] { "type": "info", "title": "\"all_solutions\" option", "body": "By default, the algorithm will return sequential available timeslots in the \"length\" duration you've specified. The available timeslots will not overlap, which means that some potential timeslots are ignored. If you want ALL timeslots (based on 15 minute intervals), then set \"all_solutions\" to true." } [/block] [block:callout] { "type": "success", "body": "If you want to conveniently re-use filters across requests, you can save filter collections using this [endpoint](/v2/docs/findtimefiltercollections)", "title": "Filter collections" } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



Makes it easy to find mutual availability across multiple resources. It will loop through all supplied resources and look for timeslots that are free for all resources. Please see the [Filters Reference](/v2/docs/find-time-filters) page for description and examples of supported filters. [block:callout] { "type": "info", "title": "Future and length formats", "body": "These can be written in \"natural language\" sentences, with an integer (e.g. 3) and a period (e.g. hours or weeks), like this: \"2 weeks\"" } [/block] [block:callout] { "type": "info", "title": "\"all_solutions\" option", "body": "By default, the algorithm will return sequential available timeslots in the \"length\" duration you've specified. The available timeslots will not overlap, which means that some potential timeslots are ignored. If you want ALL timeslots (based on 15 minute intervals), then set \"all_solutions\" to true." } [/block] [block:callout] { "type": "success", "body": "If you want to conveniently re-use filters across requests, you can save filter collections using this [endpoint](/v2/docs/findtimefiltercollections)", "title": "Filter collections" } [/block]
{"_id":"55b0272cbc77fd0d0045871e","isReference":true,"next":{"description":"","pages":[]},"parentDoc":null,"project":"550ada512188a71900453199","type":"post","version":"550bfb5522ccb01700a79469","category":"55115f836fccf32500018be4","editedParams2":true,"order":1,"slug":"findtimebulk","user":"550ada38cd78a42300ddf508","updates":[],"__v":2,"api":{"settings":"","url":"/findtime/bulk","auth":"required","examples":{"codes":[{"language":"json","code":"[\n    {\n        \"emails\": [\n            \"marty.mcfly@timekit.io\"\n        ],\n        \"filters\": {\n            \"or\": [\n                { \"specific_day\": {\"day\": \"Monday\"} },\n                { \"specific_day\": {\"day\": \"Friday\"} }\n            ]\n        },\n        \"future\": \"2 weeks\"\n    },\n    {\n        \"emails\": [\n            \"doc.brown@timekit.io\"\n        ],\n        \"filters\": {\n            \"or\": [\n                { \"specific_day\": {\"day\": \"Tuesday\"} }\n            ]\n        },\n        \"future\": \"1 weeks\"\n    }\n]\n","name":""}]},"method":"post","params":[{"desc":"array of findtime queries","in":"body","name":"#no-name#","ref":"","required":false,"type":"array_mixed","_id":"55b027a9f202b12100cda140","default":""}],"results":{"codes":[{"language":"json","code":"{\n  \"data\": [\n    [\n      {\n        \"start\": \"2015-07-27 00:00:00 Monday\",\n        \"end\": \"2015-07-27 01:00:00 Monday\"\n      },\n      {\n        \"start\": \"2015-08-03 00:00:00 Monday\",\n        \"end\": \"2015-08-03 01:00:00 Monday\"\n      },\n      {\n        \"start\": \"2015-07-24 00:00:00 Friday\",\n        \"end\": \"2015-07-24 01:00:00 Friday\"\n      },\n      {\n        \"start\": \"2015-07-31 06:00:00 Friday\",\n        \"end\": \"2015-07-31 07:00:00 Friday\"\n      }\n    ],\n    [\n      {\n        \"start\": \"2015-07-24 00:00:00 Friday\",\n        \"end\": \"2015-07-24 01:00:00 Friday\"\n      },\n      {\n        \"start\": \"2015-07-24 01:00:00 Friday\",\n        \"end\": \"2015-07-24 02:00:00 Friday\"\n      }\n    ]\n  ]\n}","name":"","status":200},{"status":400,"language":"json","code":"{}","name":""}]}},"body":"Works just the same way as a normal findtime query, but you can bulk them together in one request. See http://developers.timekit.io/docs/findtime","githubsync":"","link_external":false,"title":"/findtime/bulk","sync_unique":"","createdAt":"2015-07-22T23:28:44.110Z","editedParams":true,"excerpt":"Request several findtime queries in one go","hidden":false,"link_url":"","childrenPages":[]}

post/findtime/bulk

Request several findtime queries in one go

Body Params

no-name:
array of mixed
array of findtime queries
Works just the same way as a normal findtime query, but you can bulk them together in one request. See http://developers.timekit.io/docs/findtime

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



Works just the same way as a normal findtime query, but you can bulk them together in one request. See http://developers.timekit.io/docs/findtime
{"_id":"58b7c963301dab0f0099b756","isReference":true,"link_url":"","slug":"findtimeteam","type":"post","version":"550bfb5522ccb01700a79469","__v":3,"api":{"results":{"codes":[{"status":200,"language":"json","code":"[\n    {\n        \"start\": \"2016-02-15T09:30:00+0000\",\n        \"end\": \"2016-02-15T10:30:00+0000\",\n        \"resources\": [\n            {\n                \"resource_id\": \"bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2\",\n                \"calendar_ids\": [\n                    \"f68979ff-27da-4afd-8d0c-847f9340331b\"\n                ],\n                \"email\": \"marty.mcfly@timekit.io\",\n                \"token\": \"nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW\"\n            }\n        ]\n    },\n    {\n        \"start\": \"2016-02-15T10:30:00+0000\",\n        \"end\": \"2016-02-15T11:30:00+0000\",\n        \"resources\": [\n            {\n                \"resource_id\": \"fca27950-1be8-41e2-951c-a43a61d45d43\",\n                \"calendar_ids\": [\n                    \"c91c5d04-2a57-46c0-ab35-e489dadf132e\"\n                ],\n                \"email\": \"doc.brown@timekit.io\",\n                \"token\": \"UZpl3v3PTP1PRwqIrU0DSVpbJkNKl5gN\"\n            },\n            {\n                \"resource_id\": \"bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2\",\n                \"calendar_ids\": [\n                    \"f68979ff-27da-4afd-8d0c-847f9340331b\"\n                ],\n                \"email\": \"marty.mcfly@timekit.io\",\n                \"token\": \"nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW\"\n            }\n        ]\n    }\n]","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/findtime/team","auth":"required","examples":{"codes":[{"code":"{\n  \t\"start\": \"2 days\",\n    \"future\": \"2 weeks\",\n   \t\"length\": \"1 hour\",\n  \t\"resources\": [\n      {\n          \"resource_ids\": [\n              \"fca27950-1be8-41e2-951c-a43a61d45d43\"\n          ],\n          \"filters\": {\n              \"or\": [\n                  { \"specific_day\": {\"day\": \"Monday\"} }\n              ]\n          }\n      },\n      {\n          \"resource_ids\": [\n              \"bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2\"\n          ],\n          \"filters\": {\n              \"or\": [\n                  { \"specific_day\": {\"day\": \"Tuesday\"} }\n              ]\n          }\n      }\n\t]\n}","language":"json"}]},"method":"post","params":[{"_id":"58cf98846868a21900dab789","ref":"","in":"body","required":true,"desc":"When should we start looking for available time? Written is human language, eg. 1 day, tomorrow, 2 weeks","default":"","type":"string","name":"start"},{"_id":"58cf98846868a21900dab788","ref":"","in":"body","required":true,"desc":"How long into the future should we look for mutual availability (max 6 months)","default":"","type":"string","name":"future"},{"name":"length","_id":"58cf98846868a21900dab787","ref":"","in":"body","required":true,"desc":"How long should the availability be?","default":"","type":"string"},{"default":"","desc":"Return all overlapping timeslots? (see note)","in":"body","name":"all_solutions","ref":"","required":false,"type":"boolean","_id":"58cf98846868a21900dab786"},{"default":"","type":"boolean","name":"ignore_all_day_events","_id":"58cf98846868a21900dab785","ref":"","in":"body","required":false,"desc":"Do you want to ignore all day event in this query?"},{"desc":"An array of team members(resource_ids) with individual filters.","in":"body","name":"resources","ref":"","required":true,"type":"array_object","_id":"58b7cec7301dab0f0099b75f","default":""}]},"body":"Team availability will produce an array of available timeslots, where **any** of the team members are available. Each timeslot will contain an array of the team-members that are available in the given period.\n\nThis is helpful when you have a team, where it is not important which member is available, just that someone is. For example if you have a tech-support team, where it doesn't matter who handles an incoming issue, just that someone in the team does.\n\nFor filter documentation, please see http://developers.timekit.io/docs/findtime\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"By default, the algorithm will return sequential available timeslots in the \\\"length\\\" duration you've specified. The available timeslots will not overlap, which means that some potential timeslots are ignored. If you want ALL timeslots (based on 15 minute intervals), then set \\\"all_solutions\\\" to true.\",\n  \"title\": \"\\\"all_solutions\\\" option\"\n}\n[/block]","createdAt":"2017-03-02T07:27:31.371Z","githubsync":"","link_external":false,"parentDoc":null,"sync_unique":"","user":"58b443382654c60f00997d2b","category":"55115f836fccf32500018be4","excerpt":"Find time in a team independent of each members availability","hidden":false,"next":{"pages":[],"description":""},"order":2,"project":"550ada512188a71900453199","title":"/findtime/team","updates":[],"childrenPages":[]}

post/findtime/team

Find time in a team independent of each members availability

Body Params

start:
required
string
When should we start looking for available time? Written is human language, eg. 1 day, tomorrow, 2 weeks
future:
required
string
How long into the future should we look for mutual availability (max 6 months)
length:
required
string
How long should the availability be?
all_solutions:
boolean
Return all overlapping timeslots? (see note)
ignore_all_day_events:
boolean
Do you want to ignore all day event in this query?
resources:
required
array of objects
An array of team members(resource_ids) with individual filters.
Team availability will produce an array of available timeslots, where **any** of the team members are available. Each timeslot will contain an array of the team-members that are available in the given period. This is helpful when you have a team, where it is not important which member is available, just that someone is. For example if you have a tech-support team, where it doesn't matter who handles an incoming issue, just that someone in the team does. For filter documentation, please see http://developers.timekit.io/docs/findtime [block:callout] { "type": "info", "body": "By default, the algorithm will return sequential available timeslots in the \"length\" duration you've specified. The available timeslots will not overlap, which means that some potential timeslots are ignored. If you want ALL timeslots (based on 15 minute intervals), then set \"all_solutions\" to true.", "title": "\"all_solutions\" option" } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



Team availability will produce an array of available timeslots, where **any** of the team members are available. Each timeslot will contain an array of the team-members that are available in the given period. This is helpful when you have a team, where it is not important which member is available, just that someone is. For example if you have a tech-support team, where it doesn't matter who handles an incoming issue, just that someone in the team does. For filter documentation, please see http://developers.timekit.io/docs/findtime [block:callout] { "type": "info", "body": "By default, the algorithm will return sequential available timeslots in the \"length\" duration you've specified. The available timeslots will not overlap, which means that some potential timeslots are ignored. If you want ALL timeslots (based on 15 minute intervals), then set \"all_solutions\" to true.", "title": "\"all_solutions\" option" } [/block]
{"_id":"56b9d75ab080c217005a98d8","api":{"url":"/findtime/filtercollections","auth":"required","examples":{"codes":[{"language":"json","code":"{\n  \"and\": [\n    {\n      \"specific_day\": {\n        \"day\": \"Friday\"\n      }\n    }\n  ]\n}"}]},"method":"post","params":[{"name":"and","ref":"","required":false,"type":"array_object","_id":"56b9d75ab080c217005a98db","default":"","desc":"Add \"AND\" filters to this collection","in":"body"},{"_id":"56b9d75ab080c217005a98da","default":"","desc":"Add \"OR\" filters to this collection","in":"body","name":"or","ref":"","required":false,"type":"array_object"},{"_id":"56b9d75ab080c217005a98d9","default":"","desc":"Add \"AFTER\" filters to this collection","in":"body","name":"after","ref":"","required":false,"type":"array_object"}],"results":{"codes":[{"code":"{\n  \"data\": {\n    \"id\": \"e5a509c4-298d-44f3-ba7a-375dc5bd5e8c\",\n    \"content\": {\n      \"and\": [\n        {\n          \"specific_day\": {\n            \"day\": \"Friday\"\n          }\n        }\n      ]\n    },\n    \"created_at\": \"2016-02-08T16:01:06+0100\",\n    \"updated_at\": \"2016-02-08T16:01:06+0100\"\n  }\n}","language":"json","status":201,"name":""},{"name":"","code":"{}","language":"json","status":400}]},"settings":""},"category":"55115f836fccf32500018be4","editedParams2":true,"link_url":"","title":"/findtime/filtercollections","user":"550ada38cd78a42300ddf508","editedParams":true,"excerpt":"","isReference":true,"sync_unique":"","order":3,"parentDoc":null,"updates":[],"__v":1,"link_external":false,"next":{"description":"","pages":[]},"project":"550ada512188a71900453199","slug":"findtimefiltercollections","type":"post","version":"550bfb5522ccb01700a79469","body":"You can save a collection of filters if you want to reuse them in a FindTime request. This endpoint takes a JSON structure like the one you would normally pass to the \"filters\" key in FindTime.\n\nIn your [FindTime request](doc:findtime), use the `filtercollection_id` to pass the ID of your new filter collection and those filters will be taken into account when calculating availability.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Filters available\",\n  \"body\": \"Please see [this](doc:find-time-filters) reference for all filters that you can use\"\n}\n[/block]","createdAt":"2016-02-09T12:11:06.048Z","githubsync":"","hidden":false,"childrenPages":[]}

post/findtime/filtercollections


Body Params

and:
array of objects
Add "AND" filters to this collection
or:
array of objects
Add "OR" filters to this collection
after:
array of objects
Add "AFTER" filters to this collection
You can save a collection of filters if you want to reuse them in a FindTime request. This endpoint takes a JSON structure like the one you would normally pass to the "filters" key in FindTime. In your [FindTime request](doc:findtime), use the `filtercollection_id` to pass the ID of your new filter collection and those filters will be taken into account when calculating availability. [block:callout] { "type": "info", "title": "Filters available", "body": "Please see [this](doc:find-time-filters) reference for all filters that you can use" } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



You can save a collection of filters if you want to reuse them in a FindTime request. This endpoint takes a JSON structure like the one you would normally pass to the "filters" key in FindTime. In your [FindTime request](doc:findtime), use the `filtercollection_id` to pass the ID of your new filter collection and those filters will be taken into account when calculating availability. [block:callout] { "type": "info", "title": "Filters available", "body": "Please see [this](doc:find-time-filters) reference for all filters that you can use" } [/block]
{"_id":"56b9d787b080c217005a98dc","api":{"auth":"required","examples":{"codes":[]},"method":"get","params":[],"results":{"codes":[{"status":200,"language":"json","code":"{\n  \"data\": [\n    {\n      \"id\": \"e5a509c4-298d-44f3-ba7a-375dc5bd5e8c\",\n      \"content\": {\n        \"and\": [\n          {\n            \"specific_day\": {\n              \"day\": \"Friday\"\n            }\n          }\n        ]\n      },\n      \"created_at\": \"2016-02-08T16:01:06+0100\",\n      \"updated_at\": \"2016-02-08T16:01:06+0100\"\n    },\n    {\n      \"id\": \"0141d22d-c4bd-4bbc-a3f6-ef405414f2c4\",\n      \"content\": {\n        \"and\": [\n          {\n            \"specific_day\": {\n              \"day\": \"Monday\"\n            }\n          }\n        ]\n      },\n      \"created_at\": \"2016-02-09T13:09:54+0100\",\n      \"updated_at\": \"2016-02-09T13:09:54+0100\"\n    }\n  ]\n}","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/findtime/filtercollections"},"excerpt":"","type":"get","version":"550bfb5522ccb01700a79469","body":"Returns all filter collections tied to your user. Filter collections are simply JSON blobs of settings that goes into the \"filters\" key in FindTime requests.","link_external":false,"order":4,"parentDoc":null,"project":"550ada512188a71900453199","slug":"findtimefiltercollections-1","title":"/findtime/filtercollections","category":"55115f836fccf32500018be4","githubsync":"","hidden":false,"isReference":true,"user":"550ada38cd78a42300ddf508","__v":1,"createdAt":"2016-02-09T12:11:51.581Z","link_url":"","sync_unique":"","updates":[],"childrenPages":[]}

get/findtime/filtercollections


Returns all filter collections tied to your user. Filter collections are simply JSON blobs of settings that goes into the "filters" key in FindTime requests.

Definition

{{ api_url }}{{ page_api_url }}

Result Format



Returns all filter collections tied to your user. Filter collections are simply JSON blobs of settings that goes into the "filters" key in FindTime requests.
{"_id":"56b9d7df3d24e10d0088d088","hidden":false,"isReference":true,"link_url":"","next":{"description":"","pages":[]},"category":"55115f836fccf32500018be4","parentDoc":null,"githubsync":"","link_external":false,"order":5,"sync_unique":"","type":"put","updates":[],"createdAt":"2016-02-09T12:13:19.316Z","excerpt":"","user":"550ada38cd78a42300ddf508","body":"You can use this endpoint to overwrite an existing filter collections. Remember to supply the full set of filters as they will be replaced (not merged)","project":"550ada512188a71900453199","slug":"findtimefiltercollectionsid","title":"/findtime/filtercollections/:id","version":"550bfb5522ccb01700a79469","__v":5,"api":{"examples":{"codes":[{"language":"json","code":"{\n  \"and\": [\n    {\n      \"specific_day\": {\n        \"day\": \"Friday\"\n      }\n    }\n  ]\n}"}]},"method":"put","params":[{"ref":"","in":"body","required":false,"desc":"Add \"AND\" filters to this collection","default":"","type":"array_object","name":"and","_id":"58d294b5b807d423007c3a4c"},{"default":"","type":"array_object","name":"or","_id":"58d294b5b807d423007c3a4b","ref":"","in":"body","required":false,"desc":"Add \"OR\" filters to this collection"},{"default":"","type":"array_object","name":"after","_id":"58d294b5b807d423007c3a4a","ref":"","in":"body","required":false,"desc":"Add \"AFTER\" filters to this collection"}],"results":{"codes":[{"status":204,"language":"json","code":"{ }","name":""},{"code":"{}","name":"","status":400,"language":"json"}]},"settings":"","url":"/findtime/filtercollections/:id","auth":"required"},"childrenPages":[]}

put/findtime/filtercollections/:id


Body Params

and:
array of objects
Add "AND" filters to this collection
or:
array of objects
Add "OR" filters to this collection
after:
array of objects
Add "AFTER" filters to this collection
You can use this endpoint to overwrite an existing filter collections. Remember to supply the full set of filters as they will be replaced (not merged)

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



You can use this endpoint to overwrite an existing filter collections. Remember to supply the full set of filters as they will be replaced (not merged)
{"_id":"55933c4247f40b17003607ee","__v":81,"body":"The find time algorithm is a powerful tool to find availability by slicing data in mutiple ways using *filters*.\n\n# Quicklinks\n\nAnd/Or filters:\n- [Between timestamps](#between-timestamps-filter)\n- [Business hours](#business-hours-filter)\n- [Daytime](#daytime-filter)\n- [Only weekend](#only-weekend-filter)\n- [Exclude weekends](#exclude-weekends-filter)\n- [Specific day and time](#specific-day-and-time-filter)\n- [Specific time](#specific-time-filter)\n- [Specific day](#specific-day-filter)\n  \n# Filter types\n\nFilters are conditional rules that can exclude or include time slots based on different use cases. \nThere are 3 types of filters:\n- **OR** filters\nWill include the resulting timeslots from *any* of the supplied filters. If you supply two filters with timeslots that doesn't overlap, they will both be added to the result. Consider it equivalent of coding an OR in a conditional statement (Filter1Result OR Filter2Result OR Filter3Result ...).\n  \n- **AND** filters\nWill only include timeslots that *fit within all* of the supplied filters. Timeslots resulting from two different filters must overlap both filters to be included in the result. Consider it the equivalent of coding an AND in a conditional statement (Filter1Result AND Filter2Result AND Filter3Result ...)\n  \n# Notes\n\nYou can use **'10:30'** or just **'10'** if you want it to be 10:30 or just 10\n\n# Full example\n\nThis includes all the filters applied in one request, primarily meant as a quick syntax reference:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n   \\\"emails\\\": [\\n       \\\"doc.brown@timekit.io\\\",\\n\\t\\t\\t \\\"marty.mcfly@timekit.io\\\"\\n   ],\\n   \\\"filters\\\": {\\n       \\\"or\\\": [\\n           { \\\"specific_day\\\": {\\\"day\\\": \\\"Monday\\\"} },\\n           { \\\"specific_day_and_time\\\": {\\\"day\\\": \\\"Wednesday\\\", \\\"start\\\": 10, \\\"end\\\": 12, \\\"timezone\\\": \\\"Europe/Copenhagen\\\"}},\\n           { \\\"between_timestamps\\\": {\\\"start\\\": \\\"2016-05-26T15:30:00+00:00\\\", \\\"end\\\": \\\"2016-05-28T18:00:00+00:00\\\"}},\\n           { \\\"exclude_weekend\\\": {} },\\n           { \\\"only_weekend\\\": {} },\\n           { \\\"specific_time\\\": {\\\"start\\\": 9, \\\"end\\\": 15} }\\n           \\n       ],\\n       \\\"and\\\": [\\n           { \\\"business_hours\\\": {\\\"timezone\\\": \\\"America/Los_angeles\\\"} },\\n           { \\\"daytime\\\": {\\\"timezone\\\": \\\"Europe/Copenhagen\\\"}}\\n       ]\\n   },\\n   \\\"future\\\": \\\"1 months\\\",\\n   \\\"length\\\": \\\"15 mins\\\",\\n   \\\"sort\\\": \\\"asc\\\"\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Between timestamps filter\"\n}\n[/block]\nCan be used to find all solutions between two timestamp. The filter takes 3 arguments:\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Argument\",\n    \"h-1\": \"Description\",\n    \"h-2\": \"Required\",\n    \"0-0\": \"start\",\n    \"0-1\": \"The start timestamp of the filter\",\n    \"0-2\": \"yes\",\n    \"1-2\": \"yes\",\n    \"1-1\": \"The end timestamp of the filter\",\n    \"1-0\": \"end\",\n    \"h-3\": \"Example\",\n    \"0-3\": \"\\\"2016-05-26T15:30:00+00:00\\\"\",\n    \"1-3\": \"\\\"2016-05-28T18:00:00+00:00\\\"\",\n    \"2-0\": \"timezone\",\n    \"2-1\": \"Set timezone\",\n    \"2-2\": \"no\",\n    \"2-3\": \"\\\"Europe/Copenhagen\\\"\"\n  },\n  \"cols\": 4,\n  \"rows\": 3\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"filters\\\": {\\n        \\\"and\\\": [\\n            { \\\"between_timestamps\\\": {\\\"start\\\": \\\"2016-05-26T15:30:00+00:00\\\", \\\"end\\\": \\\"2016-05-28T18:00:00+00:00\\\", \\\"timezone\\\": \\\"Europe/Copenhagen\\\"}}\\n        ]\\n    }\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Custom timestamp formats\",\n  \"body\": \"You can set the format for input timestamps that you provide to something else that the default ISO_8601 by using the header \\\"Timekit-InputTimestampFormat\\\". Learn more [here](doc:types--formatting)\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Business hours filter\"\n}\n[/block]\nCan be used to find all solutions in business hours (9 - 18 (6pm)) in a certain timezone. \n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Argument\",\n    \"h-1\": \"Description\",\n    \"h-2\": \"Required\",\n    \"h-3\": \"Example\",\n    \"0-0\": \"timezone\",\n    \"0-1\": \"The timezone the business should be in\",\n    \"0-2\": \"no - Default will be the timezone in the request headers\",\n    \"0-3\": \"\\\"America/Los_angeles\\\"\"\n  },\n  \"cols\": 4,\n  \"rows\": 1\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"filters\\\": {\\n        \\\"and\\\": [\\n            { \\\"business_hours\\\": {\\\"timezone\\\": \\\"America/Los_angeles\\\"} },\\n          \\t{ \\\"business_hours\\\": {\\\"timezone\\\": \\\"Europe/Copenhagen\\\"} }\\n        ]\\n    }\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"You can add more then 1 business hour filter!\",\n  \"body\": \"If you add two business as 'and' filters with two different timezones, then you can make sure both timezones are in business hours!\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Daytime filter\"\n}\n[/block]\nWill only show options where its daytime (7 - 23 (11pm)) in the given timezone\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Argument\",\n    \"h-1\": \"Description\",\n    \"h-2\": \"Required\",\n    \"h-3\": \"Example\",\n    \"0-0\": \"timezone\",\n    \"0-1\": \"The timezone the business should be in\",\n    \"0-2\": \"no - Default will be the timezone in the request headers\",\n    \"0-3\": \"\\\"America/Los_angeles\\\"\"\n  },\n  \"cols\": 4,\n  \"rows\": 1\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"filters\\\": {\\n        \\\"and\\\": [\\n              { \\\"daytime\\\": {\\\"timezone\\\": \\\"America/Los_angeles\\\"} },\\n              { \\\"daytime\\\": {\\\"timezone\\\": \\\"Europe/Copenhagen\\\"} }\\n        ]\\n    }\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"You can add more then 1 daytime hour filter!\",\n  \"body\": \"If you add two daytime as 'and' filters with two different timezones, then you can make sure that all timeslots are in daytime in both timezones\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Exclude weekends filter\"\n}\n[/block]\n \nIf you need to filter out weekends (Saturdays & Sundays) you can use this filter. It takes a single argument\n\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Argument\",\n    \"h-1\": \"Description\",\n    \"h-2\": \"Required\",\n    \"0-0\": \"timezone\",\n    \"0-1\": \"The timezone\",\n    \"0-2\": \"no - default is the timezone in the header request\",\n    \"1-2\": \"yes\",\n    \"1-1\": \"The end timestamp of the filter\",\n    \"1-0\": \"end\",\n    \"h-3\": \"Example\",\n    \"0-3\": \"\\\"Europe/Copenhagen\\\"\",\n    \"1-3\": \"\\\"2015-06-23 12:00:00\\\"\",\n    \"2-0\": \"timezone\",\n    \"2-1\": \"Set timezone\",\n    \"2-2\": \"no\",\n    \"2-3\": \"\\\"Europe/Copenhagen\\\"\"\n  },\n  \"cols\": 4,\n  \"rows\": 1\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"filters\\\": {\\n        \\\"and\\\": [\\n            \\t{ \\\"exclude_weekend\\\": {}}\\n          \\t]\\n        }\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Only weekend filter\"\n}\n[/block]\n\nIf you only need timeslots in the weekend use this filter. The filter takes a single argument:\n\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Argument\",\n    \"h-1\": \"Description\",\n    \"h-2\": \"Required\",\n    \"0-0\": \"timezone\",\n    \"0-1\": \"Only weekend of the given timezone\",\n    \"0-2\": \"no - default is the timezone in the header request\",\n    \"1-2\": \"yes\",\n    \"1-1\": \"The end timestamp of the filter\",\n    \"1-0\": \"end\",\n    \"h-3\": \"Example\",\n    \"0-3\": \"\\\"Europe/Copenhagen\\\"\",\n    \"1-3\": \"\\\"2015-06-23 12:00:00\\\"\",\n    \"2-0\": \"timezone\",\n    \"2-1\": \"Set timezone\",\n    \"2-2\": \"no\",\n    \"2-3\": \"\\\"Europe/Copenhagen\\\"\"\n  },\n  \"cols\": 4,\n  \"rows\": 1\n}\n[/block]\nThis simple filter will only give you timeslots in the weekend of the given timezone!\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"filters\\\": {\\n        \\\"and\\\": [\\n            \\t{ \\\"only_weekend\\\": {}}\\n          \\t]\\n        }\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Specific day and time filter\"\n}\n[/block]\n\nIf you only need timeslots for a specific day and time, you can use this filter. The filter takes 3 argument:\n\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Argument\",\n    \"h-1\": \"Description\",\n    \"h-2\": \"Required\",\n    \"0-0\": \"day\",\n    \"0-1\": \"The day you need timeslots for\",\n    \"0-2\": \"yes\",\n    \"1-2\": \"yes\",\n    \"1-1\": \"The start hour for this filter (in 24 hour format)\",\n    \"1-0\": \"start\",\n    \"h-3\": \"Example\",\n    \"0-3\": \"\\\"Monday\\\", \\\"Tuesday\\\", \\\"Wednesday\\\", \\\"Thursday\\\", \\\"Friday\\\", \\\"Saturday\\\" or \\\"Sunday\\\"\",\n    \"1-3\": \"10\",\n    \"2-0\": \"end\",\n    \"2-1\": \"The end hour for this filter (in 24 hour format)\",\n    \"2-2\": \"yes\",\n    \"2-3\": \"12\"\n  },\n  \"cols\": 4,\n  \"rows\": 3\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"filters\\\": {\\n        \\\"and\\\": [\\n            { \\\"specific_day_and_time\\\": {\\\"day\\\": \\\"Monday\\\", \\\"start\\\": 10, \\\"end\\\": 12}}\\n          ]\\n        }\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nThis will give you all timestamps on mondays between 10 & 12.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"The start & end uses 24 hour clock\",\n  \"body\": \"So if you need between 10 - 11 in the evening, you need to set start & end to 22 & 23\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Specific time filter\"\n}\n[/block]\nIf you only need timeslots for a specific time interval, you can use this filter. The filter takes a single argument:\n\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Argument\",\n    \"h-1\": \"Description\",\n    \"h-2\": \"Required\",\n    \"0-2\": \"yes\",\n    \"0-1\": \"The start hour for this filter (in 24 hour format)\",\n    \"0-0\": \"start\",\n    \"h-3\": \"Example\",\n    \"0-3\": \"10\",\n    \"1-0\": \"end\",\n    \"1-1\": \"The end hour for this filter (in 24 hour format)\",\n    \"1-2\": \"yes\",\n    \"1-3\": \"12\",\n    \"2-0\": \"timezone\",\n    \"2-2\": \"no - default from the request headers\",\n    \"2-3\": \"\\\"Europe/Copenhagen\\\"\",\n    \"2-1\": \"That timezone the start & end hour should make\"\n  },\n  \"cols\": 4,\n  \"rows\": 3\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"filters\\\": {\\n        \\\"and\\\": [\\n            { \\\"specific_time\\\": {\\\"start\\\": 10, \\\"end\\\": 12}}\\n          ]\\n        }\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Specific day filter\"\n}\n[/block]\n\nIf you only need timeslots for a specific day, you can use this filter. The filter takes a single argument:\n\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Argument\",\n    \"h-1\": \"Description\",\n    \"h-2\": \"Required\",\n    \"0-0\": \"day\",\n    \"0-1\": \"The day you need timeslots for\",\n    \"0-2\": \"yes\",\n    \"1-2\": \"yes\",\n    \"1-1\": \"The end timestamp of the filter\",\n    \"1-0\": \"end\",\n    \"h-3\": \"Example\",\n    \"0-3\": \"\\\"Monday\\\", \\\"Tuesday\\\", \\\"Wednesday\\\", \\\"Thursday\\\", \\\"Friday\\\", \\\"Saturday\\\" or \\\"Sunday\\\"\",\n    \"1-3\": \"\\\"2015-06-23 12:00:00\\\"\",\n    \"2-0\": \"timezone\",\n    \"2-1\": \"Set timezone\",\n    \"2-2\": \"no\",\n    \"2-3\": \"\\\"Europe/Copenhagen\\\"\"\n  },\n  \"cols\": 4,\n  \"rows\": 1\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"filters\\\": {\\n        \\\"and\\\": [\\n            { \\\"specific_day\\\": {\\\"day\\\": \\\"Monday\\\"}}\\n        ]\\n   }\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIf you need either monday or friday you can do this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"filters\\\": {\\n        \\\"or\\\": [\\n          { \\\"specific_day\\\": {\\\"day\\\": \\\"Monday\\\"}},\\n          { \\\"specific_day\\\": {\\\"day\\\": \\\"Friday\\\"}}\\n        ]\\n   }\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"If you need to add a specific time of the day also, use specific_day_and_time filter!\"\n}\n[/block]","excerpt":"","link_external":false,"project":"550ada512188a71900453199","slug":"find-time-filters","githubsync":"","isReference":true,"sync_unique":"","updates":[],"version":"550bfb5522ccb01700a79469","api":{"url":"","auth":"required","params":[],"results":{"codes":[{"status":200,"language":"json","code":"{}","name":""},{"language":"json","code":"{}","name":"","status":400}]},"settings":""},"category":"55115f836fccf32500018be4","createdAt":"2015-07-01T01:02:58.296Z","link_url":"","title":"Availability filters","type":"basic","user":"550ada38cd78a42300ddf508","hidden":false,"next":{"description":"","pages":[]},"order":6,"parentDoc":null,"childrenPages":[]}

Availability filters


The find time algorithm is a powerful tool to find availability by slicing data in mutiple ways using *filters*. # Quicklinks And/Or filters: - [Between timestamps](#between-timestamps-filter) - [Business hours](#business-hours-filter) - [Daytime](#daytime-filter) - [Only weekend](#only-weekend-filter) - [Exclude weekends](#exclude-weekends-filter) - [Specific day and time](#specific-day-and-time-filter) - [Specific time](#specific-time-filter) - [Specific day](#specific-day-filter) # Filter types Filters are conditional rules that can exclude or include time slots based on different use cases. There are 3 types of filters: - **OR** filters Will include the resulting timeslots from *any* of the supplied filters. If you supply two filters with timeslots that doesn't overlap, they will both be added to the result. Consider it equivalent of coding an OR in a conditional statement (Filter1Result OR Filter2Result OR Filter3Result ...). - **AND** filters Will only include timeslots that *fit within all* of the supplied filters. Timeslots resulting from two different filters must overlap both filters to be included in the result. Consider it the equivalent of coding an AND in a conditional statement (Filter1Result AND Filter2Result AND Filter3Result ...) # Notes You can use **'10:30'** or just **'10'** if you want it to be 10:30 or just 10 # Full example This includes all the filters applied in one request, primarily meant as a quick syntax reference: [block:code] { "codes": [ { "code": "{\n \"emails\": [\n \"doc.brown@timekit.io\",\n\t\t\t \"marty.mcfly@timekit.io\"\n ],\n \"filters\": {\n \"or\": [\n { \"specific_day\": {\"day\": \"Monday\"} },\n { \"specific_day_and_time\": {\"day\": \"Wednesday\", \"start\": 10, \"end\": 12, \"timezone\": \"Europe/Copenhagen\"}},\n { \"between_timestamps\": {\"start\": \"2016-05-26T15:30:00+00:00\", \"end\": \"2016-05-28T18:00:00+00:00\"}},\n { \"exclude_weekend\": {} },\n { \"only_weekend\": {} },\n { \"specific_time\": {\"start\": 9, \"end\": 15} }\n \n ],\n \"and\": [\n { \"business_hours\": {\"timezone\": \"America/Los_angeles\"} },\n { \"daytime\": {\"timezone\": \"Europe/Copenhagen\"}}\n ]\n },\n \"future\": \"1 months\",\n \"length\": \"15 mins\",\n \"sort\": \"asc\"\n}", "language": "json" } ] } [/block] [block:api-header] { "type": "basic", "title": "Between timestamps filter" } [/block] Can be used to find all solutions between two timestamp. The filter takes 3 arguments: [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "0-0": "start", "0-1": "The start timestamp of the filter", "0-2": "yes", "1-2": "yes", "1-1": "The end timestamp of the filter", "1-0": "end", "h-3": "Example", "0-3": "\"2016-05-26T15:30:00+00:00\"", "1-3": "\"2016-05-28T18:00:00+00:00\"", "2-0": "timezone", "2-1": "Set timezone", "2-2": "no", "2-3": "\"Europe/Copenhagen\"" }, "cols": 4, "rows": 3 } [/block] [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n { \"between_timestamps\": {\"start\": \"2016-05-26T15:30:00+00:00\", \"end\": \"2016-05-28T18:00:00+00:00\", \"timezone\": \"Europe/Copenhagen\"}}\n ]\n }", "language": "json" } ] } [/block] [block:callout] { "type": "info", "title": "Custom timestamp formats", "body": "You can set the format for input timestamps that you provide to something else that the default ISO_8601 by using the header \"Timekit-InputTimestampFormat\". Learn more [here](doc:types--formatting)" } [/block] [block:api-header] { "type": "basic", "title": "Business hours filter" } [/block] Can be used to find all solutions in business hours (9 - 18 (6pm)) in a certain timezone. [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "h-3": "Example", "0-0": "timezone", "0-1": "The timezone the business should be in", "0-2": "no - Default will be the timezone in the request headers", "0-3": "\"America/Los_angeles\"" }, "cols": 4, "rows": 1 } [/block] [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n { \"business_hours\": {\"timezone\": \"America/Los_angeles\"} },\n \t{ \"business_hours\": {\"timezone\": \"Europe/Copenhagen\"} }\n ]\n }", "language": "json" } ] } [/block] [block:callout] { "type": "info", "title": "You can add more then 1 business hour filter!", "body": "If you add two business as 'and' filters with two different timezones, then you can make sure both timezones are in business hours!" } [/block] [block:api-header] { "type": "basic", "title": "Daytime filter" } [/block] Will only show options where its daytime (7 - 23 (11pm)) in the given timezone [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "h-3": "Example", "0-0": "timezone", "0-1": "The timezone the business should be in", "0-2": "no - Default will be the timezone in the request headers", "0-3": "\"America/Los_angeles\"" }, "cols": 4, "rows": 1 } [/block] [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n { \"daytime\": {\"timezone\": \"America/Los_angeles\"} },\n { \"daytime\": {\"timezone\": \"Europe/Copenhagen\"} }\n ]\n }", "language": "json" } ] } [/block] [block:callout] { "type": "info", "title": "You can add more then 1 daytime hour filter!", "body": "If you add two daytime as 'and' filters with two different timezones, then you can make sure that all timeslots are in daytime in both timezones" } [/block] [block:api-header] { "type": "basic", "title": "Exclude weekends filter" } [/block] If you need to filter out weekends (Saturdays & Sundays) you can use this filter. It takes a single argument [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "0-0": "timezone", "0-1": "The timezone", "0-2": "no - default is the timezone in the header request", "1-2": "yes", "1-1": "The end timestamp of the filter", "1-0": "end", "h-3": "Example", "0-3": "\"Europe/Copenhagen\"", "1-3": "\"2015-06-23 12:00:00\"", "2-0": "timezone", "2-1": "Set timezone", "2-2": "no", "2-3": "\"Europe/Copenhagen\"" }, "cols": 4, "rows": 1 } [/block] [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n \t{ \"exclude_weekend\": {}}\n \t]\n }", "language": "json" } ] } [/block] [block:api-header] { "type": "basic", "title": "Only weekend filter" } [/block] If you only need timeslots in the weekend use this filter. The filter takes a single argument: [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "0-0": "timezone", "0-1": "Only weekend of the given timezone", "0-2": "no - default is the timezone in the header request", "1-2": "yes", "1-1": "The end timestamp of the filter", "1-0": "end", "h-3": "Example", "0-3": "\"Europe/Copenhagen\"", "1-3": "\"2015-06-23 12:00:00\"", "2-0": "timezone", "2-1": "Set timezone", "2-2": "no", "2-3": "\"Europe/Copenhagen\"" }, "cols": 4, "rows": 1 } [/block] This simple filter will only give you timeslots in the weekend of the given timezone! [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n \t{ \"only_weekend\": {}}\n \t]\n }", "language": "json" } ] } [/block] [block:api-header] { "type": "basic", "title": "Specific day and time filter" } [/block] If you only need timeslots for a specific day and time, you can use this filter. The filter takes 3 argument: [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "0-0": "day", "0-1": "The day you need timeslots for", "0-2": "yes", "1-2": "yes", "1-1": "The start hour for this filter (in 24 hour format)", "1-0": "start", "h-3": "Example", "0-3": "\"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\" or \"Sunday\"", "1-3": "10", "2-0": "end", "2-1": "The end hour for this filter (in 24 hour format)", "2-2": "yes", "2-3": "12" }, "cols": 4, "rows": 3 } [/block] [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n { \"specific_day_and_time\": {\"day\": \"Monday\", \"start\": 10, \"end\": 12}}\n ]\n }", "language": "json" } ] } [/block] This will give you all timestamps on mondays between 10 & 12. [block:callout] { "type": "warning", "title": "The start & end uses 24 hour clock", "body": "So if you need between 10 - 11 in the evening, you need to set start & end to 22 & 23" } [/block] [block:api-header] { "type": "basic", "title": "Specific time filter" } [/block] If you only need timeslots for a specific time interval, you can use this filter. The filter takes a single argument: [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "0-2": "yes", "0-1": "The start hour for this filter (in 24 hour format)", "0-0": "start", "h-3": "Example", "0-3": "10", "1-0": "end", "1-1": "The end hour for this filter (in 24 hour format)", "1-2": "yes", "1-3": "12", "2-0": "timezone", "2-2": "no - default from the request headers", "2-3": "\"Europe/Copenhagen\"", "2-1": "That timezone the start & end hour should make" }, "cols": 4, "rows": 3 } [/block] [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n { \"specific_time\": {\"start\": 10, \"end\": 12}}\n ]\n }", "language": "json" } ] } [/block] [block:api-header] { "type": "basic", "title": "Specific day filter" } [/block] If you only need timeslots for a specific day, you can use this filter. The filter takes a single argument: [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "0-0": "day", "0-1": "The day you need timeslots for", "0-2": "yes", "1-2": "yes", "1-1": "The end timestamp of the filter", "1-0": "end", "h-3": "Example", "0-3": "\"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\" or \"Sunday\"", "1-3": "\"2015-06-23 12:00:00\"", "2-0": "timezone", "2-1": "Set timezone", "2-2": "no", "2-3": "\"Europe/Copenhagen\"" }, "cols": 4, "rows": 1 } [/block] [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n { \"specific_day\": {\"day\": \"Monday\"}}\n ]\n }", "language": "json" } ] } [/block] If you need either monday or friday you can do this: [block:code] { "codes": [ { "code": "\"filters\": {\n \"or\": [\n { \"specific_day\": {\"day\": \"Monday\"}},\n { \"specific_day\": {\"day\": \"Friday\"}}\n ]\n }", "language": "json" } ] } [/block] [block:callout] { "type": "success", "title": "If you need to add a specific time of the day also, use specific_day_and_time filter!" } [/block]
The find time algorithm is a powerful tool to find availability by slicing data in mutiple ways using *filters*. # Quicklinks And/Or filters: - [Between timestamps](#between-timestamps-filter) - [Business hours](#business-hours-filter) - [Daytime](#daytime-filter) - [Only weekend](#only-weekend-filter) - [Exclude weekends](#exclude-weekends-filter) - [Specific day and time](#specific-day-and-time-filter) - [Specific time](#specific-time-filter) - [Specific day](#specific-day-filter) # Filter types Filters are conditional rules that can exclude or include time slots based on different use cases. There are 3 types of filters: - **OR** filters Will include the resulting timeslots from *any* of the supplied filters. If you supply two filters with timeslots that doesn't overlap, they will both be added to the result. Consider it equivalent of coding an OR in a conditional statement (Filter1Result OR Filter2Result OR Filter3Result ...). - **AND** filters Will only include timeslots that *fit within all* of the supplied filters. Timeslots resulting from two different filters must overlap both filters to be included in the result. Consider it the equivalent of coding an AND in a conditional statement (Filter1Result AND Filter2Result AND Filter3Result ...) # Notes You can use **'10:30'** or just **'10'** if you want it to be 10:30 or just 10 # Full example This includes all the filters applied in one request, primarily meant as a quick syntax reference: [block:code] { "codes": [ { "code": "{\n \"emails\": [\n \"doc.brown@timekit.io\",\n\t\t\t \"marty.mcfly@timekit.io\"\n ],\n \"filters\": {\n \"or\": [\n { \"specific_day\": {\"day\": \"Monday\"} },\n { \"specific_day_and_time\": {\"day\": \"Wednesday\", \"start\": 10, \"end\": 12, \"timezone\": \"Europe/Copenhagen\"}},\n { \"between_timestamps\": {\"start\": \"2016-05-26T15:30:00+00:00\", \"end\": \"2016-05-28T18:00:00+00:00\"}},\n { \"exclude_weekend\": {} },\n { \"only_weekend\": {} },\n { \"specific_time\": {\"start\": 9, \"end\": 15} }\n \n ],\n \"and\": [\n { \"business_hours\": {\"timezone\": \"America/Los_angeles\"} },\n { \"daytime\": {\"timezone\": \"Europe/Copenhagen\"}}\n ]\n },\n \"future\": \"1 months\",\n \"length\": \"15 mins\",\n \"sort\": \"asc\"\n}", "language": "json" } ] } [/block] [block:api-header] { "type": "basic", "title": "Between timestamps filter" } [/block] Can be used to find all solutions between two timestamp. The filter takes 3 arguments: [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "0-0": "start", "0-1": "The start timestamp of the filter", "0-2": "yes", "1-2": "yes", "1-1": "The end timestamp of the filter", "1-0": "end", "h-3": "Example", "0-3": "\"2016-05-26T15:30:00+00:00\"", "1-3": "\"2016-05-28T18:00:00+00:00\"", "2-0": "timezone", "2-1": "Set timezone", "2-2": "no", "2-3": "\"Europe/Copenhagen\"" }, "cols": 4, "rows": 3 } [/block] [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n { \"between_timestamps\": {\"start\": \"2016-05-26T15:30:00+00:00\", \"end\": \"2016-05-28T18:00:00+00:00\", \"timezone\": \"Europe/Copenhagen\"}}\n ]\n }", "language": "json" } ] } [/block] [block:callout] { "type": "info", "title": "Custom timestamp formats", "body": "You can set the format for input timestamps that you provide to something else that the default ISO_8601 by using the header \"Timekit-InputTimestampFormat\". Learn more [here](doc:types--formatting)" } [/block] [block:api-header] { "type": "basic", "title": "Business hours filter" } [/block] Can be used to find all solutions in business hours (9 - 18 (6pm)) in a certain timezone. [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "h-3": "Example", "0-0": "timezone", "0-1": "The timezone the business should be in", "0-2": "no - Default will be the timezone in the request headers", "0-3": "\"America/Los_angeles\"" }, "cols": 4, "rows": 1 } [/block] [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n { \"business_hours\": {\"timezone\": \"America/Los_angeles\"} },\n \t{ \"business_hours\": {\"timezone\": \"Europe/Copenhagen\"} }\n ]\n }", "language": "json" } ] } [/block] [block:callout] { "type": "info", "title": "You can add more then 1 business hour filter!", "body": "If you add two business as 'and' filters with two different timezones, then you can make sure both timezones are in business hours!" } [/block] [block:api-header] { "type": "basic", "title": "Daytime filter" } [/block] Will only show options where its daytime (7 - 23 (11pm)) in the given timezone [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "h-3": "Example", "0-0": "timezone", "0-1": "The timezone the business should be in", "0-2": "no - Default will be the timezone in the request headers", "0-3": "\"America/Los_angeles\"" }, "cols": 4, "rows": 1 } [/block] [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n { \"daytime\": {\"timezone\": \"America/Los_angeles\"} },\n { \"daytime\": {\"timezone\": \"Europe/Copenhagen\"} }\n ]\n }", "language": "json" } ] } [/block] [block:callout] { "type": "info", "title": "You can add more then 1 daytime hour filter!", "body": "If you add two daytime as 'and' filters with two different timezones, then you can make sure that all timeslots are in daytime in both timezones" } [/block] [block:api-header] { "type": "basic", "title": "Exclude weekends filter" } [/block] If you need to filter out weekends (Saturdays & Sundays) you can use this filter. It takes a single argument [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "0-0": "timezone", "0-1": "The timezone", "0-2": "no - default is the timezone in the header request", "1-2": "yes", "1-1": "The end timestamp of the filter", "1-0": "end", "h-3": "Example", "0-3": "\"Europe/Copenhagen\"", "1-3": "\"2015-06-23 12:00:00\"", "2-0": "timezone", "2-1": "Set timezone", "2-2": "no", "2-3": "\"Europe/Copenhagen\"" }, "cols": 4, "rows": 1 } [/block] [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n \t{ \"exclude_weekend\": {}}\n \t]\n }", "language": "json" } ] } [/block] [block:api-header] { "type": "basic", "title": "Only weekend filter" } [/block] If you only need timeslots in the weekend use this filter. The filter takes a single argument: [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "0-0": "timezone", "0-1": "Only weekend of the given timezone", "0-2": "no - default is the timezone in the header request", "1-2": "yes", "1-1": "The end timestamp of the filter", "1-0": "end", "h-3": "Example", "0-3": "\"Europe/Copenhagen\"", "1-3": "\"2015-06-23 12:00:00\"", "2-0": "timezone", "2-1": "Set timezone", "2-2": "no", "2-3": "\"Europe/Copenhagen\"" }, "cols": 4, "rows": 1 } [/block] This simple filter will only give you timeslots in the weekend of the given timezone! [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n \t{ \"only_weekend\": {}}\n \t]\n }", "language": "json" } ] } [/block] [block:api-header] { "type": "basic", "title": "Specific day and time filter" } [/block] If you only need timeslots for a specific day and time, you can use this filter. The filter takes 3 argument: [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "0-0": "day", "0-1": "The day you need timeslots for", "0-2": "yes", "1-2": "yes", "1-1": "The start hour for this filter (in 24 hour format)", "1-0": "start", "h-3": "Example", "0-3": "\"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\" or \"Sunday\"", "1-3": "10", "2-0": "end", "2-1": "The end hour for this filter (in 24 hour format)", "2-2": "yes", "2-3": "12" }, "cols": 4, "rows": 3 } [/block] [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n { \"specific_day_and_time\": {\"day\": \"Monday\", \"start\": 10, \"end\": 12}}\n ]\n }", "language": "json" } ] } [/block] This will give you all timestamps on mondays between 10 & 12. [block:callout] { "type": "warning", "title": "The start & end uses 24 hour clock", "body": "So if you need between 10 - 11 in the evening, you need to set start & end to 22 & 23" } [/block] [block:api-header] { "type": "basic", "title": "Specific time filter" } [/block] If you only need timeslots for a specific time interval, you can use this filter. The filter takes a single argument: [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "0-2": "yes", "0-1": "The start hour for this filter (in 24 hour format)", "0-0": "start", "h-3": "Example", "0-3": "10", "1-0": "end", "1-1": "The end hour for this filter (in 24 hour format)", "1-2": "yes", "1-3": "12", "2-0": "timezone", "2-2": "no - default from the request headers", "2-3": "\"Europe/Copenhagen\"", "2-1": "That timezone the start & end hour should make" }, "cols": 4, "rows": 3 } [/block] [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n { \"specific_time\": {\"start\": 10, \"end\": 12}}\n ]\n }", "language": "json" } ] } [/block] [block:api-header] { "type": "basic", "title": "Specific day filter" } [/block] If you only need timeslots for a specific day, you can use this filter. The filter takes a single argument: [block:parameters] { "data": { "h-0": "Argument", "h-1": "Description", "h-2": "Required", "0-0": "day", "0-1": "The day you need timeslots for", "0-2": "yes", "1-2": "yes", "1-1": "The end timestamp of the filter", "1-0": "end", "h-3": "Example", "0-3": "\"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\" or \"Sunday\"", "1-3": "\"2015-06-23 12:00:00\"", "2-0": "timezone", "2-1": "Set timezone", "2-2": "no", "2-3": "\"Europe/Copenhagen\"" }, "cols": 4, "rows": 1 } [/block] [block:code] { "codes": [ { "code": "\"filters\": {\n \"and\": [\n { \"specific_day\": {\"day\": \"Monday\"}}\n ]\n }", "language": "json" } ] } [/block] If you need either monday or friday you can do this: [block:code] { "codes": [ { "code": "\"filters\": {\n \"or\": [\n { \"specific_day\": {\"day\": \"Monday\"}},\n { \"specific_day\": {\"day\": \"Friday\"}}\n ]\n }", "language": "json" } ] } [/block] [block:callout] { "type": "success", "title": "If you need to add a specific time of the day also, use specific_day_and_time filter!" } [/block]
{"_id":"550bfb5622ccb01700a7946c","body":"Get basic information about the authenticated user/resources","createdAt":"2015-03-20T10:47:35.719Z","excerpt":"","link_external":false,"api":{"method":"get","params":[],"results":{"codes":[{"status":200,"language":"json","code":"{\n  \"data\": {\n    \"id\": \"78a4d873-2a68-41c6-bdd4-c0ca5b35efd3\",\n\t\t\"first_name\": \"Dr. Emmett\",\n\t\t\"last_name\": \"Brown\",\n\t\t\"name\": \"Dr. Emmett Brown\",\n\t\t\"email\": \"doc.brown@timekit.io\",\n\t\t\"image\": \"http:\\/\\/www.gravatar.com\\/avatar\\/7a613e5348d6347627693502580f5aad\",\n\t\t\"activated\": true,\n\t\t\"timezone\": \"America\\/Los_Angeles\",\n\t\t\"token\": \"nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW\",\n\t\t\"last_sync\": null,\n\t\t\"token_generated_at\": null\n\t}\n}","name":""},{"status":422,"language":"json","code":"{\n\t'error': 'Error description'\n}","name":""},{"status":401,"language":"text","code":"{\n\t'error': 'Unauthorized access, please login'\n}"}]},"settings":"","url":"/resources/me","auth":"required","examples":{"codes":[]}},"order":0,"parentDoc":null,"slug":"resourcesme","type":"get","updates":[],"isReference":true,"link_url":"","hidden":false,"next":{"pages":[],"description":""},"sync_unique":"","title":"/resources/me","version":"550bfb5522ccb01700a79469","__v":8,"githubsync":"","user":"550ada38cd78a42300ddf508","category":"550bfb5622ccb01700a7946b","project":"550ada512188a71900453199","childrenPages":[]}

get/resources/me


Get basic information about the authenticated user/resources

Definition

{{ api_url }}{{ page_api_url }}

Result Format



Get basic information about the authenticated user/resources
{"_id":"56605ad06c2a8d0d00276646","editedParams2":true,"isReference":true,"link_external":false,"order":1,"body":"Will return the current timezone for any resource on the platform (queried by email).\n\nIf connected with a Google account, the timezone is automatically fetched from Google calendar. The timezone can be also be set manually using the [PUT] /resources/me endpoint.","category":"550bfb5622ccb01700a7946b","hidden":false,"project":"550ada512188a71900453199","version":"550bfb5522ccb01700a79469","__v":1,"createdAt":"2015-12-03T15:08:00.456Z","excerpt":"","parentDoc":null,"sync_unique":"","updates":[],"type":"get","user":"550bf7b2eb24860d00e6a33b","api":{"auth":"required","method":"get","params":[{"in":"query","_id":"56605ad06c2a8d0d00276647","required":true,"desc":"The email of the user you want the timezone for","default":"","type":"string","name":"Email","ref":""}],"results":{"codes":[{"status":200,"language":"json","code":"{\n  \"data\": {\n    \"timezone\": \"Europe/Stockholm\",\n    \"utc_offset\": 1\n  }\n}","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/resources/timezone/:email","examples":{"codes":[]}},"editedParams":true,"githubsync":"","link_url":"","slug":"resourcestimezoneemail","title":"/resources/timezone/:email","next":{"description":"","pages":[]},"childrenPages":[]}

get/resources/timezone/:email


Query Params

Email:
required
string
The email of the user you want the timezone for
Will return the current timezone for any resource on the platform (queried by email). If connected with a Google account, the timezone is automatically fetched from Google calendar. The timezone can be also be set manually using the [PUT] /resources/me endpoint.

Definition

{{ api_url }}{{ page_api_url }}

Result Format



Will return the current timezone for any resource on the platform (queried by email). If connected with a Google account, the timezone is automatically fetched from Google calendar. The timezone can be also be set manually using the [PUT] /resources/me endpoint.
{"_id":"5511364e0c1a08190077f6a6","next":{"description":"","pages":[]},"order":2,"parentDoc":null,"title":"/resources","type":"post","__v":4,"category":"550bfb5622ccb01700a7946b","createdAt":"2015-03-24T10:02:54.871Z","editedParams2":true,"excerpt":"Create a resource","githubsync":"","isReference":true,"link_external":false,"api":{"examples":{"codes":[{"code":"curl -X POST \\\n\t\t -H 'Timekit-App: back-to-the-future' \\\n     -d '{\n           \"email\": \"doc.brown@timekit.io\",\n           \"timezone\": \"America/Los_Angeles\",\n           \"name\": \"Doc Brown\",\n    \t\t\t \"password\": \"FluxCapacitator\"\n       }' \\\n  https://api.timekit.io/v2/resources","language":"curl"},{"code":"{\n    \"email\": \"doc.brown@timekit.io\",\n    \"timezone\": \"America/Los_Angeles\",\n    \"first_name\": \"Emmet\",\n    \"last_name\": \"Brown\",\n    \"password\": \"FluxCapacitator\"\n}","language":"json"}]},"method":"post","params":[{"_id":"594b8f39da95db0025b11ad6","ref":"","in":"body","required":true,"desc":"Set the name of the resource","default":"","type":"string","name":"name"},{"_id":"5511364e0c1a08190077f6a8","ref":"","in":"body","required":true,"desc":"Timezone of the resources","default":"","type":"string","name":"timezone"},{"_id":"5511364e0c1a08190077f6a7","ref":"","in":"body","required":false,"desc":"Email of the resources","default":"","type":"string","name":"email"},{"_id":"5511364e0c1a08190077f6aa","ref":"","in":"body","required":false,"desc":"First name of the resources, useful if you're creating users as resources","default":"","type":"string","name":"first_name"},{"_id":"5511364e0c1a08190077f6a9","ref":"","in":"body","required":false,"desc":"Last name of the resources","default":"","type":"string","name":"last_name"},{"_id":"56004c9397f69f1700f21905","ref":"","in":"body","required":false,"desc":"Password of the resources (if not set, a random password will be assigned - can be reset subsequently)","default":"","type":"string","name":"password"}],"results":{"codes":[{"name":"","code":"{\n  \"data\": {\n    \"id\": \"d187d6e0-d6cb-409a-ae60-45a8fd0ec879\",\n    \"first_name\": \"Emmet\",\n    \"last_name\": \"Brown\",\n    \"name\": \"Emmet Brown\",\n    \"email\": \"doc.brown@timekit.io\",\n    \"image\": \"http://www.link-to-img.com/image.png\",\n    \"activated\": false,\n    \"timezone\": \"America/Los_Angeles\",\n    \"last_sync\": null,\n    \"api_token\": \"nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW\"\n  }\n}","language":"json","status":201},{"name":"","code":"{}","language":"json","status":400},{"language":"json","status":422,"code":"{\n  \"errors\": {\n    \"name\": [\n    \t\"The name field is required.\"\n    ],\n    \"timezone\": [\n    \t\"The timezone field is required.\"\n    ]\n  }\n}"}]},"settings":"5759474aace5c30e00cb24cd","url":"/resources","auth":"never"},"hidden":false,"slug":"resources","updates":[],"version":"550bfb5522ccb01700a79469","body":"Create a new resource.\n\nBookable resources can represent people (employees, vendors), items (screwdriver, musical instrument) or locations (meeting rooms).\n\nWhen you interact with the API to create new bookings and fetch availability, you will have to authenticate as your resource using an email and API token. The `api_token` returned in the response is your credentials that you must save and use for future API requests. See [authentication](doc:authentication) for more info.\n\nDo also note that this endpoint simply creates a plain Timekit resources. If you want to create a user-resource based on a Google account, please see [[GET] /accounts/google/signup](doc:accountsgooglesignup)\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Authenticate as app owner!\",\n  \"body\": \"To programmatically create resources within your app, you must authenticate as the owner (user) of your app. Remember to also set your app slug in the Timekit-App header. This ensures that only you can add new resources to your app in Timekit.\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"Timezone must be a valid timezone, formatted like this \\\"Europe/Copenhagen\\\" - [see list of valid timezones](http://en.wikipedia.org/wiki/List_of_tz_database_time_zones)\",\n  \"title\": \"Timezone format\"\n}\n[/block]","editedParams":true,"link_url":"","project":"550ada512188a71900453199","sync_unique":"","user":"550ada38cd78a42300ddf508","childrenPages":[]}

post/resources

Create a resource

Body Params

name:
required
string
Set the name of the resource
timezone:
required
string
Timezone of the resources
email:
string
Email of the resources
first_name:
string
First name of the resources, useful if you're creating users as resources
last_name:
string
Last name of the resources
password:
string
Password of the resources (if not set, a random password will be assigned - can be reset subsequently)
Create a new resource. Bookable resources can represent people (employees, vendors), items (screwdriver, musical instrument) or locations (meeting rooms). When you interact with the API to create new bookings and fetch availability, you will have to authenticate as your resource using an email and API token. The `api_token` returned in the response is your credentials that you must save and use for future API requests. See [authentication](doc:authentication) for more info. Do also note that this endpoint simply creates a plain Timekit resources. If you want to create a user-resource based on a Google account, please see [[GET] /accounts/google/signup](doc:accountsgooglesignup) [block:callout] { "type": "warning", "title": "Authenticate as app owner!", "body": "To programmatically create resources within your app, you must authenticate as the owner (user) of your app. Remember to also set your app slug in the Timekit-App header. This ensures that only you can add new resources to your app in Timekit." } [/block] [block:callout] { "type": "info", "body": "Timezone must be a valid timezone, formatted like this \"Europe/Copenhagen\" - [see list of valid timezones](http://en.wikipedia.org/wiki/List_of_tz_database_time_zones)", "title": "Timezone format" } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



Create a new resource. Bookable resources can represent people (employees, vendors), items (screwdriver, musical instrument) or locations (meeting rooms). When you interact with the API to create new bookings and fetch availability, you will have to authenticate as your resource using an email and API token. The `api_token` returned in the response is your credentials that you must save and use for future API requests. See [authentication](doc:authentication) for more info. Do also note that this endpoint simply creates a plain Timekit resources. If you want to create a user-resource based on a Google account, please see [[GET] /accounts/google/signup](doc:accountsgooglesignup) [block:callout] { "type": "warning", "title": "Authenticate as app owner!", "body": "To programmatically create resources within your app, you must authenticate as the owner (user) of your app. Remember to also set your app slug in the Timekit-App header. This ensures that only you can add new resources to your app in Timekit." } [/block] [block:callout] { "type": "info", "body": "Timezone must be a valid timezone, formatted like this \"Europe/Copenhagen\" - [see list of valid timezones](http://en.wikipedia.org/wiki/List_of_tz_database_time_zones)", "title": "Timezone format" } [/block]
{"_id":"55cd57361450350d006d85e1","api":{"auth":"required","examples":{"codes":[]},"method":"post","params":[{"default":"","desc":"Email of the user/resource you want to reset the password for","name":"email","ref":"","required":true,"type":"string","in":"body","_id":"55cd57361450350d006d85e2"}],"results":{"codes":[{"name":"","status":200,"language":"json","code":""},{"language":"json","code":"{}","name":"","status":400}]},"settings":"","url":"/resources/resetpassword"},"body":"Use this endpoint to reset the password for a resource. The resource will receive a temporary password that you can use for authentication and set a new password using the update resource endpoint.\n\nThe entire flow:\n\n1. Call [POST] /v2/resources/resetpassword with your email in a JSON body, like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n\\t\\\"email\\\": \\\"my@email.com\\\"\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n2. You should receive an email with a temporary password. Use this password to authenticate using the [[POST] /auth](https://dash.readme.io/project/timekit/v2/docs/auth) endpoint. In that response there will be a **api-token** which you need to use for subsequent [authentication](doc:authentication).\n\n3. Last step is to call [[PUT] /v2/resources/me](https://dash.readme.io/project/timekit/v2/docs/resourcesme-1) and set the new password for your user/resource. Note that this endpoint is gated and you need to set the appropriate  [\"Authorization\" header](doc:authentication) to access it, using your e-mail and the API-token from the previous step.","editedParams":true,"editedParams2":true,"link_external":false,"order":3,"parentDoc":null,"__v":1,"isReference":true,"link_url":"","project":"550ada512188a71900453199","slug":"resourcesresetpassword","title":"/resources/resetpassword","user":"550ada38cd78a42300ddf508","version":"550bfb5522ccb01700a79469","createdAt":"2015-08-14T02:49:26.094Z","excerpt":"","sync_unique":"","type":"post","githubsync":"","hidden":false,"updates":[],"category":"550bfb5622ccb01700a7946b","next":{"description":"","pages":[]},"childrenPages":[]}

post/resources/resetpassword


Body Params

email:
required
string
Email of the user/resource you want to reset the password for
Use this endpoint to reset the password for a resource. The resource will receive a temporary password that you can use for authentication and set a new password using the update resource endpoint. The entire flow: 1. Call [POST] /v2/resources/resetpassword with your email in a JSON body, like this: [block:code] { "codes": [ { "code": "{\n\t\"email\": \"my@email.com\"\n}", "language": "json" } ] } [/block] 2. You should receive an email with a temporary password. Use this password to authenticate using the [[POST] /auth](https://dash.readme.io/project/timekit/v2/docs/auth) endpoint. In that response there will be a **api-token** which you need to use for subsequent [authentication](doc:authentication). 3. Last step is to call [[PUT] /v2/resources/me](https://dash.readme.io/project/timekit/v2/docs/resourcesme-1) and set the new password for your user/resource. Note that this endpoint is gated and you need to set the appropriate ["Authorization" header](doc:authentication) to access it, using your e-mail and the API-token from the previous step.

Definition

{{ api_url }}{{ page_api_url }}


Use this endpoint to reset the password for a resource. The resource will receive a temporary password that you can use for authentication and set a new password using the update resource endpoint. The entire flow: 1. Call [POST] /v2/resources/resetpassword with your email in a JSON body, like this: [block:code] { "codes": [ { "code": "{\n\t\"email\": \"my@email.com\"\n}", "language": "json" } ] } [/block] 2. You should receive an email with a temporary password. Use this password to authenticate using the [[POST] /auth](https://dash.readme.io/project/timekit/v2/docs/auth) endpoint. In that response there will be a **api-token** which you need to use for subsequent [authentication](doc:authentication). 3. Last step is to call [[PUT] /v2/resources/me](https://dash.readme.io/project/timekit/v2/docs/resourcesme-1) and set the new password for your user/resource. Note that this endpoint is gated and you need to set the appropriate ["Authorization" header](doc:authentication) to access it, using your e-mail and the API-token from the previous step.
{"_id":"5567ae8d820d1a3700874e8c","body":"Update the current user's/resource's properties like name, password and timezone.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Email is immutable\",\n  \"body\": \"Resource e-mail cannot be changed once created. Please create a new resource if you would like to use another email.\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"Note that if you have a Google account connecting and are attempting to update the timezone, it will be overridden by the timezone specified in Google calendar. Therefore, change the timezone in Google calendar instead.\",\n  \"title\": \"Google timezone\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"If you're attempting to reset your password, remember you'll need to supply the correct [\\\"Authorization\\\"](doc:authentication) header. Read the [reset password guide](doc:usersresetpassword) for more info.\",\n  \"title\": \"Reset password\"\n}\n[/block]","category":"550bfb5622ccb01700a7946b","link_external":false,"parentDoc":null,"sync_unique":"","user":"550bf7b2eb24860d00e6a33b","api":{"url":"/resources/me","auth":"required","examples":{"codes":[]},"method":"put","params":[{"_id":"594b9153169246000f3b2e14","ref":"","in":"body","required":false,"desc":"","default":"","type":"string","name":"name"},{"_id":"5567ae8d820d1a3700874e91","ref":"","in":"body","required":false,"desc":"First name of the user","default":"","type":"string","name":"first_name"},{"_id":"5567ae8d820d1a3700874e90","ref":"","in":"body","required":false,"desc":"Last name of the user","default":"","type":"string","name":"last_name"},{"_id":"5567ae8d820d1a3700874e8e","ref":"","in":"body","required":false,"desc":"User's timezone following \"area/city\" schema","default":"","type":"string","name":"timezone"},{"_id":"5567ae8d820d1a3700874e8d","ref":"","in":"body","required":false,"desc":"User's password in cleartext","default":"","type":"string","name":"password"}],"results":{"codes":[{"language":"json","code":"{\n  \"first_name\": \"Marty\",\n  \"last_name\": \"McFly\",\n\t\"password\": \"my-new-password\",\n  \"timezone\": \"America/Los_angeles\"\n}","name":"","status":200},{"code":"{}","name":"","status":400,"language":"json"}]},"settings":""},"createdAt":"2015-05-29T00:10:53.039Z","editedParams2":true,"githubsync":"","isReference":true,"project":"550ada512188a71900453199","type":"put","__v":4,"editedParams":true,"excerpt":"","next":{"description":"","pages":[]},"order":4,"slug":"resourcesme-1","title":"/resources/me","hidden":false,"link_url":"","updates":["56673cb25d00370d00ede6e8"],"version":"550bfb5522ccb01700a79469","childrenPages":[]}

put/resources/me


Body Params

name:
string
first_name:
string
First name of the user
last_name:
string
Last name of the user
timezone:
string
User's timezone following "area/city" schema
password:
string
User's password in cleartext
Update the current user's/resource's properties like name, password and timezone. [block:callout] { "type": "warning", "title": "Email is immutable", "body": "Resource e-mail cannot be changed once created. Please create a new resource if you would like to use another email." } [/block] [block:callout] { "type": "warning", "body": "Note that if you have a Google account connecting and are attempting to update the timezone, it will be overridden by the timezone specified in Google calendar. Therefore, change the timezone in Google calendar instead.", "title": "Google timezone" } [/block] [block:callout] { "type": "info", "body": "If you're attempting to reset your password, remember you'll need to supply the correct [\"Authorization\"](doc:authentication) header. Read the [reset password guide](doc:usersresetpassword) for more info.", "title": "Reset password" } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Result Format



Update the current user's/resource's properties like name, password and timezone. [block:callout] { "type": "warning", "title": "Email is immutable", "body": "Resource e-mail cannot be changed once created. Please create a new resource if you would like to use another email." } [/block] [block:callout] { "type": "warning", "body": "Note that if you have a Google account connecting and are attempting to update the timezone, it will be overridden by the timezone specified in Google calendar. Therefore, change the timezone in Google calendar instead.", "title": "Google timezone" } [/block] [block:callout] { "type": "info", "body": "If you're attempting to reset your password, remember you'll need to supply the correct [\"Authorization\"](doc:authentication) header. Read the [reset password guide](doc:usersresetpassword) for more info.", "title": "Reset password" } [/block]
{"_id":"575febc89b1a9a220067c1ed","category":"575fe7d3b6600917005fd878","createdAt":"2016-06-14T11:34:32.351Z","isReference":true,"project":"550ada512188a71900453199","title":"/projects","updates":[],"body":"[Booking.js](http://github.com/timekit-io/booking-js) is a UI widget component that integrates seamlessly with the availability and booking features of Timekit. You can embed it within your own web app and offer your visitors an easy way to book Timekit resources.\n\n**The booking.js widget can be used in two ways**: \n1) Passing config to it on-the-fly.\n2) Have it load the config remotely from our datastore. These endpoints are used for just that.\n\nThis endpoint lists a user's projects and are meant for administration purpose only (check out [[GET] /projects/embed/:id](doc:projectsembed) and [[GET] /projects/hosted/:id](doc:projectshosted) endpoint which are publicly accessible).\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"You need to generate a special widget API token for safe access in the browser, please see [[POST] /credentials](doc:credentials)\",\n  \"title\": \"Widget credentials/API token\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Booking.js widget is open source\",\n  \"body\": \"The widget is available on GitHub here: https://github.com/timekit-io/booking-js\\nIf you pass a `widgetId` or `widgetSlug` to the library config, it will automatically fetch the config and load the initialize the widget with the config you've saved here on Timekit.\"\n}\n[/block]","hidden":false,"user":"550bf7b2eb24860d00e6a33b","api":{"results":{"codes":[{"language":"json","code":"{\n  \"data\": [{\n    \"id\": \"00f4d4ac-a64b-4752-95db-309d5bddf72c\",\n    \"name\": \"Martys test-project\",\n    \"slug\": \"martys-project\",\n    \"config\": {\n      \"email\": \"marty.mcfly@timekit.io\",\n      \"calendar\": \"b7bd09ab-bbb5-4c83-ae5f-ee0ede4124ce\",\n      \"apiToken\": \"E6W4riZQcBfaAJkspVgODZD69qDNMZiV\",\n      \"bookingGraph\": \"instant\",\n      \"name\": \"Marty's calendar\",\n      \"localization\": {\n        \"timeDateFormat\": \"12h-mdy-sun\",\n        \"showTimezoneHelper\": true\n      },\n      \"timekitFindTime\": {\n        \"filters\": {\n          \"and\": [{\n            \"exclude_weekend\": []\n          }]\n        },\n        \"calendar_ids\": [\n\t\t\t\t\t\"b7bd09ab-2bb5-4c83-ae5f-ee0e5e4124ce\", \n          \"15b18888-d56a-4f7c-8b31-643140be7dc5\"\n        ],\n        \"emails\": [],\n        \"length\": \"30 minutes\"\n      },\n      \"timekitCreateBooking\": {\n        \"event\": {\n          \"where\": \"Hill Valley\"\n        }\n      }\n    },\n    \"created_at\": \"2016-04-27T15:24:07+0200\",\n    \"updated_at\": \"2016-06-02T09:05:44+0200\"\n  }, {\n    \"id\": \"1a54db8e-46c3-48b6-8644-6ffd164de1b6\",\n    \"name\": \"Another test project\",\n    \"slug\": \"c9f3s40k\",\n    \"config\": {\n      \"email\": \"marty.mcfly@timekit.io\",\n      \"calendar\": \"61263a27-5e20-4f80-a7f5-9ac0c3b66cf3\",\n      \"apiToken\": \"Aq8mLNjdXKcqxNFNihDIpoKPlHxrFBil\",\n      \"bookingGraph\": \"confirm_decline\",\n      \"name\": \"Marty the Mayn\",\n      \"timekitFindTime\": {\n        \"length\": \"1 hour\"\n      },\n      \"localization\": {\n        \"timeDateFormat\": \"12h-mdy-sun\",\n        \"showTimezoneHelper\": false\n      },\n      \"timekitCreateBooking\": {\n        \"event\": {\n          \"where\": \"Skype\"\n        }\n      },\n      \"bookingFields\": {\n        \"comment\": {\n          \"enabled\": true\n        },\n        \"phone\": {\n          \"enabled\": false\n        },\n        \"voip\": {\n          \"enabled\": false\n        }\n      },\n    },\n    \"created_at\": \"2016-04-29T17:04:57+0200\",\n    \"updated_at\": \"2016-05-25T08:31:12+0200\"\n  }]\n}","name":"","status":200},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/projects","auth":"required","examples":{"codes":[]},"method":"get","params":[]},"link_external":false,"parentDoc":null,"type":"get","version":"550bfb5522ccb01700a79469","githubsync":"","excerpt":"","link_url":"","order":0,"slug":"projects","sync_unique":"","__v":4,"next":{"description":"","pages":[]},"childrenPages":[]}

get/projects


[Booking.js](http://github.com/timekit-io/booking-js) is a UI widget component that integrates seamlessly with the availability and booking features of Timekit. You can embed it within your own web app and offer your visitors an easy way to book Timekit resources. **The booking.js widget can be used in two ways**: 1) Passing config to it on-the-fly. 2) Have it load the config remotely from our datastore. These endpoints are used for just that. This endpoint lists a user's projects and are meant for administration purpose only (check out [[GET] /projects/embed/:id](doc:projectsembed) and [[GET] /projects/hosted/:id](doc:projectshosted) endpoint which are publicly accessible). [block:callout] { "type": "info", "body": "You need to generate a special widget API token for safe access in the browser, please see [[POST] /credentials](doc:credentials)", "title": "Widget credentials/API token" } [/block] [block:callout] { "type": "info", "title": "Booking.js widget is open source", "body": "The widget is available on GitHub here: https://github.com/timekit-io/booking-js\nIf you pass a `widgetId` or `widgetSlug` to the library config, it will automatically fetch the config and load the initialize the widget with the config you've saved here on Timekit." } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Result Format



[Booking.js](http://github.com/timekit-io/booking-js) is a UI widget component that integrates seamlessly with the availability and booking features of Timekit. You can embed it within your own web app and offer your visitors an easy way to book Timekit resources. **The booking.js widget can be used in two ways**: 1) Passing config to it on-the-fly. 2) Have it load the config remotely from our datastore. These endpoints are used for just that. This endpoint lists a user's projects and are meant for administration purpose only (check out [[GET] /projects/embed/:id](doc:projectsembed) and [[GET] /projects/hosted/:id](doc:projectshosted) endpoint which are publicly accessible). [block:callout] { "type": "info", "body": "You need to generate a special widget API token for safe access in the browser, please see [[POST] /credentials](doc:credentials)", "title": "Widget credentials/API token" } [/block] [block:callout] { "type": "info", "title": "Booking.js widget is open source", "body": "The widget is available on GitHub here: https://github.com/timekit-io/booking-js\nIf you pass a `widgetId` or `widgetSlug` to the library config, it will automatically fetch the config and load the initialize the widget with the config you've saved here on Timekit." } [/block]
{"_id":"575fefb5cc89d61700b8d9e4","version":"550bfb5522ccb01700a79469","api":{"settings":"","url":"/projects/embed/:id","auth":"required","examples":{"codes":[]},"method":"get","params":[{"type":"string","name":"id","in":"path","_id":"575fefb6cc89d61700b8d9e5","ref":"","required":true,"desc":"ID of the widget you want to retrieve","default":""}],"results":{"codes":[{"status":200,"language":"json","code":"{\n  \"data\": {\n    \"id\": \"826ddc8e-8698-45be-9320-0c81dcf797d9\",\n    \"slug\": \"my-test-project\",\n    \"config\": {\n      \"email\": \"marty.mcfly@timekit.io\",\n      \"calendar\": \"3653d9a9-46d3-4270-8d34-34b3d871128d\",\n      \"apiToken\": \"xwcgiK7u7EZSpIkCSt3Oaq1eFy1fZBJA\"\n    }\n  }\n}","name":""},{"status":400,"language":"json","code":"{}","name":""}]}},"createdAt":"2016-06-14T11:51:17.999Z","order":1,"user":"550bf7b2eb24860d00e6a33b","isReference":true,"link_url":"","body":"Retrieve a specific project and it's config. \n\nIdeal if you want to load a widget config to booking.js based on a known project ID (for e.g. embedding)\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Publicly accessible endpoint\",\n  \"body\": \"This endpoint is publicly accessible without authentication and can be used for embedding the widget on public-facing websites and alike.\"\n}\n[/block]","excerpt":"","githubsync":"","hidden":false,"sync_unique":"","title":"/projects/embed/:id","editedParams":true,"editedParams2":true,"link_external":false,"parentDoc":null,"slug":"projectsembed","type":"get","updates":[],"__v":1,"category":"575fe7d3b6600917005fd878","project":"550ada512188a71900453199","next":{"description":"","pages":[]},"childrenPages":[]}

get/projects/embed/:id


Path Params

id:
required
string
ID of the widget you want to retrieve
Retrieve a specific project and it's config. Ideal if you want to load a widget config to booking.js based on a known project ID (for e.g. embedding) [block:callout] { "type": "success", "title": "Publicly accessible endpoint", "body": "This endpoint is publicly accessible without authentication and can be used for embedding the widget on public-facing websites and alike." } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Result Format



Retrieve a specific project and it's config. Ideal if you want to load a widget config to booking.js based on a known project ID (for e.g. embedding) [block:callout] { "type": "success", "title": "Publicly accessible endpoint", "body": "This endpoint is publicly accessible without authentication and can be used for embedding the widget on public-facing websites and alike." } [/block]
{"_id":"575fefdc4715f61700ae84d8","isReference":true,"link_external":false,"excerpt":"","editedParams":true,"editedParams2":true,"hidden":false,"slug":"projectshosted","type":"get","version":"550bfb5522ccb01700a79469","__v":1,"body":"Retrieve a specific project and it's config.\n\nIdeal if you want to load a widget config to booking.js based on a known project slug (for e.g. building project pages where a human-friendly slug is passed in the URL)\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Publicly accessible endpoint\",\n  \"body\": \"This endpoint is publicly accessible without authentication and can be used for embedding the widget on public-facing websites and alike.\"\n}\n[/block]","category":"575fe7d3b6600917005fd878","githubsync":"","sync_unique":"","title":"/projects/hosted/:slug","updates":[],"api":{"method":"get","params":[{"default":"","type":"string","name":"slug","in":"path","_id":"575fefb6cc89d61700b8d9e5","ref":"","required":true,"desc":"Slug of the project you want to retrieve"}],"results":{"codes":[{"status":200,"language":"json","code":"{\n  \"data\": {\n    \"id\": \"826ddc8e-8698-45be-9320-0c81dcf797d9\",\n    \"slug\": \"my-test-project\",\n    \"config\": {\n      \"email\": \"marty.mcfly@timekit.io\",\n      \"calendar\": \"3653d9a9-46d3-4270-8d34-34b3d871128d\",\n      \"apiToken\": \"xwcgiK7u7EZSpIkCSt3Oaq1eFy1fZBJA\"\n    }\n  }\n}","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/projects/hosted/:slug","auth":"required","examples":{"codes":[]}},"createdAt":"2016-06-14T11:51:56.439Z","link_url":"","order":2,"parentDoc":null,"project":"550ada512188a71900453199","user":"550bf7b2eb24860d00e6a33b","next":{"description":"","pages":[]},"childrenPages":[]}

get/projects/hosted/:slug


Path Params

slug:
required
string
Slug of the project you want to retrieve
Retrieve a specific project and it's config. Ideal if you want to load a widget config to booking.js based on a known project slug (for e.g. building project pages where a human-friendly slug is passed in the URL) [block:callout] { "type": "success", "title": "Publicly accessible endpoint", "body": "This endpoint is publicly accessible without authentication and can be used for embedding the widget on public-facing websites and alike." } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Result Format



Retrieve a specific project and it's config. Ideal if you want to load a widget config to booking.js based on a known project slug (for e.g. building project pages where a human-friendly slug is passed in the URL) [block:callout] { "type": "success", "title": "Publicly accessible endpoint", "body": "This endpoint is publicly accessible without authentication and can be used for embedding the widget on public-facing websites and alike." } [/block]
{"_id":"575ff0d9c0bca70e00afbf9a","__v":1,"createdAt":"2016-06-14T11:56:09.122Z","editedParams2":true,"githubsync":"","order":3,"sync_unique":"","title":"/projects/:id","body":"Update an existing project.","editedParams":true,"excerpt":"","slug":"projectsid-1","type":"put","updates":[],"api":{"auth":"required","examples":{"codes":[{"language":"json","code":"{\n  \"name\": \"My Test Project\",\n  \"slug\": \"my-test-project\",\n  \"config\": {\n    \"email\": \"marty.mcfly@timekit.io\",\n    \"calendar\": \"3653d9a9-46d3-4270-8d34-34b3d871128d\",\n    \"apiToken\": \"xwcgiK7u7EZSpIkCSt3Oaq1eFy1fZBJA\",\n    \"app\": \"back-to-the-future\"\n  }\n}"}]},"method":"put","params":[{"required":true,"desc":"ID of the project you want to update","default":"","type":"string","name":"id","in":"path","_id":"575ff0d9c0bca70e00afbf9b","ref":""},{"desc":"Name of the project","default":"","type":"string","name":"name","in":"body","_id":"575fee98af3e090e00107fcf","ref":"","required":false},{"ref":"","required":false,"desc":"A unique slug","default":"","type":"string","name":"slug","in":"body","_id":"575fee98af3e090e00107fce"},{"required":true,"desc":"The widget config you want to save","default":"","type":"string","name":"config","in":"body","_id":"575fee98af3e090e00107fcd","ref":""}],"results":{"codes":[{"status":204,"language":"json","code":"","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/projects/:id"},"category":"575fe7d3b6600917005fd878","link_url":"","parentDoc":null,"project":"550ada512188a71900453199","version":"550bfb5522ccb01700a79469","hidden":false,"isReference":true,"link_external":false,"user":"550bf7b2eb24860d00e6a33b","next":{"description":"","pages":[]},"childrenPages":[]}

put/projects/:id


Path Params

id:
required
string
ID of the project you want to update

Body Params

name:
string
Name of the project
slug:
string
A unique slug
config:
required
string
The widget config you want to save
Update an existing project.

Definition

{{ api_url }}{{ page_api_url }}

Examples



Update an existing project.
{"_id":"575fee98af3e090e00107fcc","excerpt":"","githubsync":"","link_external":false,"updates":[],"api":{"auth":"required","examples":{"codes":[{"code":"{\n  \"name\": \"My Test Project\",\n  \"slug\": \"my-test-project\",\n  \"config\": {\n    \"email\": \"marty.mcfly@timekit.io\",\n    \"calendar\": \"3653d9a9-46d3-4270-8d34-34b3d871128d\",\n    \"apiToken\": \"xwcgiK7u7EZSpIkCSt3Oaq1eFy1fZBJA\",\n    \"app\": \"back-to-the-future\"\n  }\n}","language":"json"}]},"method":"post","params":[{"name":"name","in":"body","_id":"575fee98af3e090e00107fcf","ref":"","required":true,"desc":"Give the project a name","default":"","type":"string"},{"desc":"A unique slug","default":"","type":"string","name":"slug","in":"body","_id":"575fee98af3e090e00107fce","ref":"","required":true},{"name":"config","in":"body","_id":"575fee98af3e090e00107fcd","ref":"","required":true,"desc":"The widget config you want to save","default":"","type":"string"}],"results":{"codes":[{"name":"","code":"{\n  \"data\": {\n    \"id\": \"826ddc8e-8698-45be-9320-0c81dcf797d9\",\n    \"name\": \"My Test Project\",\n    \"slug\": \"my-test-project\",\n    \"config\": {\n      \"email\": \"marty.mcfly@timekit.io\",\n      \"calendar\": \"3653d9a9-46d3-4270-8d34-34b3d871128d\",\n      \"apiToken\": \"xwcgiK7u7EZSpIkCSt3Oaq1eFy1fZBJA\",\n      \"app\": \"back-to-the-future\"\n    }\n  }\n}","language":"json","status":200},{"name":"","code":"{}","language":"json","status":400}]},"settings":"","url":"/projects"},"createdAt":"2016-06-14T11:46:32.777Z","order":4,"parentDoc":null,"project":"550ada512188a71900453199","type":"post","__v":1,"isReference":true,"link_url":"","title":"/projects","body":"Save a new project. \n\nThe slug can be used to fetch the widget config afterwards using a human-friendly slug instead of the ID (for instance when used on hosted project pages like http://myapp.com/my-project-slug)","category":"575fe7d3b6600917005fd878","editedParams2":true,"hidden":false,"slug":"projects-1","sync_unique":"","user":"550bf7b2eb24860d00e6a33b","version":"550bfb5522ccb01700a79469","editedParams":true,"next":{"description":"","pages":[]},"childrenPages":[]}

post/projects


Body Params

name:
required
string
Give the project a name
slug:
required
string
A unique slug
config:
required
string
The widget config you want to save
Save a new project. The slug can be used to fetch the widget config afterwards using a human-friendly slug instead of the ID (for instance when used on hosted project pages like http://myapp.com/my-project-slug)

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



Save a new project. The slug can be used to fetch the widget config afterwards using a human-friendly slug instead of the ID (for instance when used on hosted project pages like http://myapp.com/my-project-slug)
{"_id":"575ff1172a034b19001d8d25","createdAt":"2016-06-14T11:57:11.623Z","editedParams":true,"excerpt":"","link_external":false,"slug":"projectsid-2","title":"/projects/:id","updates":[],"githubsync":"","hidden":false,"order":5,"project":"550ada512188a71900453199","sync_unique":"","api":{"auth":"required","examples":{"codes":[]},"method":"delete","params":[{"default":"","type":"string","name":"id","in":"path","_id":"575fefb6cc89d61700b8d9e5","ref":"","required":true,"desc":"ID of the project you want to delete"}],"results":{"codes":[{"status":204,"language":"json","code":"","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/projects/:id"},"link_url":"","type":"delete","user":"550bf7b2eb24860d00e6a33b","version":"550bfb5522ccb01700a79469","__v":1,"body":"Delete a specific project.","category":"575fe7d3b6600917005fd878","editedParams2":true,"isReference":true,"parentDoc":null,"next":{"description":"","pages":[]},"childrenPages":[]}

delete/projects/:id


Path Params

id:
required
string
ID of the project you want to delete
Delete a specific project.

Definition

{{ api_url }}{{ page_api_url }}


Delete a specific project.
{"_id":"55666ccf979a3c2500bbb041","editedParams":true,"sync_unique":"","title":"/events","version":"550bfb5522ccb01700a79469","category":"55113dab9171e82b00897160","body":"This endpoint can be used to manually save events to Timekit\n\nIf your user/resource has a connected google account then we will write the event to google and start a google sync right away.\n\nThis means that the event will first be saved to the google account and will be available a few seconds later via the [[GET] /events](doc:events) or [[GET] /calendars?include=events](doc:calendars) endpoint","editedParams2":true,"githubsync":"","hidden":false,"link_external":false,"order":0,"slug":"events-1","api":{"auth":"required","examples":{"codes":[{"code":"curl -X POST \\\n\t\t -H 'Timekit-App: back-to-the-future' \\\n     -u marty.mcfly@timekit.io:CPDqMLOoT4quO7j71jfcD9VlYpJBDPqI \\\n     -d '{\n       \"start\": \"1955-11-12T21:30:00-07:00\",\n       \"end\": \"1955-11-12T22:15:00-07:00\",\n       \"what\": \"Catch the lightning\",\n       \"where\": \"Courthouse, Hill Valley, CA 95420, USA\",\n       \"calendar_id\": \"bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2\",\n       \"allDay\": false,\n       \"description\": \"The lightning strikes at 10:04 PM exactly! I need you to be there Doc!.\"\n    }'\\\n   \thttps://api.timekit.io/v2/events","language":"curl"}]},"method":"post","params":[{"ref":"","required":true,"type":"datetime","_id":"55666ccf979a3c2500bbb047","default":"","desc":"Start of the event","in":"body","name":"start"},{"desc":"End of the event","in":"body","name":"end","ref":"","required":true,"type":"datetime","_id":"55666ccf979a3c2500bbb046","default":""},{"in":"body","name":"what","ref":"","required":true,"type":"string","_id":"55666ccf979a3c2500bbb045","default":"","desc":"What is the event? 'Strategy meeting' or 'Coffee with Peter'"},{"required":true,"type":"string","_id":"55666ccf979a3c2500bbb043","default":"","desc":"Where is the event taking place?","in":"body","name":"where","ref":""},{"in":"body","name":"calendar_id","ref":"","required":true,"type":"string","_id":"55666ccf979a3c2500bbb044","default":"","desc":"Uuid of the calendar to add the event to"},{"required":false,"type":"array_string","_id":"557227d08956493700aae2bb","default":"","desc":"A list of emails to invite as participants","in":"body","name":"participants","ref":""},{"name":"invite","ref":"","required":false,"type":"boolean","_id":"55666ccf979a3c2500bbb042","default":"false","desc":"Should we notify the participant?","in":"body"},{"type":"string","_id":"5643bc01c6e9600d006bd706","default":"","desc":"A custom description for the event","in":"body","name":"description","ref":"","required":false},{"default":"","desc":"Set your own rsvp, allowed values: accepted, needsAction, declined, tentative","in":"body","name":"my_rsvp","ref":"","required":false,"type":"string","_id":"564d9d3ef3171a0d0056e4a4"},{"desc":"This will trigger a sync with the associated provider and return the Event object from the database","in":"body","name":"sync_provider","ref":"","required":false,"type":"boolean","_id":"56605ef66c2a8d0d0027665f","default":"false"},{"in":"body","name":"all_day","ref":"","required":false,"type":"boolean","_id":"56685d36acfd301700c4eac4","default":"false","desc":"if set to true, we will only send date (Y-m-d) to google, so it will be handled as a true all day event"}],"results":{"codes":[{"language":"json","status":201,"name":"","code":" "},{"name":"","code":"{ }","language":"json","status":400}]},"settings":"","url":"/events"},"user":"550ada38cd78a42300ddf508","excerpt":"","isReference":true,"link_url":"","next":{"description":"","pages":[]},"updates":[],"createdAt":"2015-05-28T01:18:07.525Z","parentDoc":null,"project":"550ada512188a71900453199","type":"post","__v":7,"childrenPages":[]}

post/events


Body Params

start:
required
datetime
Start of the event
end:
required
datetime
End of the event
what:
required
string
What is the event? 'Strategy meeting' or 'Coffee with Peter'
where:
required
string
Where is the event taking place?
calendar_id:
required
string
Uuid of the calendar to add the event to
participants:
array of strings
A list of emails to invite as participants
invite:
booleanfalse
Should we notify the participant?
description:
string
A custom description for the event
my_rsvp:
string
Set your own rsvp, allowed values: accepted, needsAction, declined, tentative
sync_provider:
booleanfalse
This will trigger a sync with the associated provider and return the Event object from the database
all_day:
booleanfalse
if set to true, we will only send date (Y-m-d) to google, so it will be handled as a true all day event
This endpoint can be used to manually save events to Timekit If your user/resource has a connected google account then we will write the event to google and start a google sync right away. This means that the event will first be saved to the google account and will be available a few seconds later via the [[GET] /events](doc:events) or [[GET] /calendars?include=events](doc:calendars) endpoint

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



This endpoint can be used to manually save events to Timekit If your user/resource has a connected google account then we will write the event to google and start a google sync right away. This means that the event will first be saved to the google account and will be available a few seconds later via the [[GET] /events](doc:events) or [[GET] /calendars?include=events](doc:calendars) endpoint
{"_id":"55113eb49171e82b00897162","link_url":"","version":"550bfb5522ccb01700a79469","editedParams":true,"excerpt":"","githubsync":"","hidden":false,"isReference":true,"order":1,"parentDoc":null,"slug":"events","body":"Retrieve events for the authenticated user/resource, across every calendar.\n\nIf you want events for a particular calendar, you can call [[GET] /calendars?include=events](doc:calendars) and get events grouped by which calendar they belong to.\n\nYou can also get the participants for an event by adding: `[GET] /events?include=participants`\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"All timestamp are UTC!\"\n}\n[/block]","createdAt":"2015-03-24T10:38:44.841Z","title":"/events","updates":[],"user":"550ada38cd78a42300ddf508","category":"55113dab9171e82b00897160","editedParams2":true,"link_external":false,"next":{"description":"","pages":[]},"project":"550ada512188a71900453199","sync_unique":"","type":"get","__v":1,"api":{"url":"/events","auth":"required","examples":{"codes":[{"language":"curl","code":"curl -X GET \\\n\t\t -H 'Timekit-App: back-to-the-future' \\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n     https://api.timekit.io/v2/events"}]},"method":"get","params":[{"default":"","desc":"Start date to get events from","name":"start","ref":"","required":true,"type":"timestamp","in":"query","_id":"55113eb49171e82b00897164"},{"desc":"End date to get events to","name":"end","ref":"","required":true,"type":"timestamp","in":"query","_id":"55113eb49171e82b00897163","default":""}],"results":{"codes":[{"language":"json","code":"{\n\t\"data\": [\n    {\n      \"id\": \"31c354d2-7249-4877-b9b7-d076e8e4b676\",\n      \"start\": \"1955-11-12T21:30:00-07:00\",\n      \"end\": \"1955-11-12T22:15:00-07:00\",\n      \"what\": \"Catch the lightning\",\n      \"where\": \"Courthouse, Hill Valley, CA 95420, USA\",\n      \"calendar_id\": \"bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2\",\n      \"allDay\": false,\n      \"description\": \"The lightning strikes at 10:04 PM exactly! I need you to be there Doc!.\"\n    },\n    {\n      \"id\": \"8d30b27e-ffd3-4b41-a7c0-da334d4ebbdd\",\n      \"start\": \"1955-11-05T09:30:00-07:00\",\n      \"end\": \"1955-11-05T09:45:00-07:00\",\n      \"what\": \"Deliver the Pacard to the auto shop\",\n      \"where\": \"Western Auto Store, Hill Valley, CA 95420, USA\",\n      \"calendar_id\": \"c91c5d04-2a57-46c0-ab35-e489dadf132e\",\n      \"allDay\": false,\n      \"description\": \"The clutch needs tightening\",\n    }    \n  ]\n}","name":"","status":200},{"code":"{\n  \"errors\": {\n    \"start\": [\n      \"The start field is required.\"\n    ],\n    \"end\": [\n      \"The end field is required.\"\n    ]\n  }\n}","name":"","status":422,"language":"json"}]},"settings":""},"childrenPages":[]}

get/events


Query Params

start:
required
timestamp
Start date to get events from
end:
required
timestamp
End date to get events to
Retrieve events for the authenticated user/resource, across every calendar. If you want events for a particular calendar, you can call [[GET] /calendars?include=events](doc:calendars) and get events grouped by which calendar they belong to. You can also get the participants for an event by adding: `[GET] /events?include=participants` [block:callout] { "type": "info", "title": "All timestamp are UTC!" } [/block]

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



Retrieve events for the authenticated user/resource, across every calendar. If you want events for a particular calendar, you can call [[GET] /calendars?include=events](doc:calendars) and get events grouped by which calendar they belong to. You can also get the participants for an event by adding: `[GET] /events?include=participants` [block:callout] { "type": "info", "title": "All timestamp are UTC!" } [/block]
{"_id":"56957bff60c4b20d0050a3e7","excerpt":"","link_external":false,"order":2,"parentDoc":null,"editedParams":true,"githubsync":"","next":{"description":"","pages":[]},"updates":[],"__v":2,"api":{"settings":"","url":"/events/:id","auth":"required","examples":{"codes":[{"language":"curl","code":"curl -X GET \\\n     -H 'Timekit-App: back-to-the-future' \\\n     -u doc.brown@timekit.io:nvHfRSlhvsnlg4rS7Wt28Ty47qdgegwSu3YK7hPW \\\n     https://api.timekit.io/v2/events/31c354d2-7249-4877-b9b7-d076e8e4b676"}]},"method":"get","params":[{"default":"","desc":"the id of the event","in":"path","name":"id","ref":"","required":false,"type":"string","_id":"56957cb90c650a2300250608"}],"results":{"codes":[{"name":"","status":200,"language":"json","code":"{\n  \"data\": {\n    \"id\": \"31c354d2-7249-4877-b9b7-d076e8e4b676\",\n    \"start\": \"1955-11-12T21:30:00-07:00\",\n    \"end\": \"1955-11-12T22:15:00-07:00\",\n    \"what\": \"Catch the lightning\",\n    \"where\": \"Courthouse, Hill Valley, CA 95420, USA\",\n    \"calendar_id\": \"bfa0b9fa-36aa-4ae6-8096-f3b20fbed1d2\",\n    \"allDay\": false,\n    \"description\": \"The lightning strikes at 10:04 PM exactly! I need you to be there Doc!.\"\n  }\n}"},{"language":"json","code":"{\n  \"error\": \"Resource does not exist\"\n}","name":"","status":404},{"status":403,"language":"json","code":"{\n  \"errors\": \"You are not allowed to do this!\"\n}"}]}},"isReference":true,"link_url":"","project":"550ada512188a71900453199","title":"/events/:id","user":"550ada38cd78a42300ddf508","body":"You can retrieve event by their id, but only events that are owned by the user/resource authenticated.","category":"55113dab9171e82b00897160","createdAt":"2016-01-12T22:19:43.983Z","editedParams2":true,"hidden":false,"slug":"eventsid-1","sync_unique":"","type":"get","version":"550bfb5522ccb01700a79469","childrenPages":[]}

get/events/:id


Path Params

id:
string
the id of the event
You can retrieve event by their id, but only events that are owned by the user/resource authenticated.

Definition

{{ api_url }}{{ page_api_url }}

Examples


Result Format



You can retrieve event by their id, but only events that are owned by the user/resource authenticated.
{"_id":"564c95012dc03121001b3437","__v":3,"category":"55113dab9171e82b00897160","githubsync":"","title":"/events/:id","type":"put","api":{"auth":"required","method":"put","params":[{"required":false,"desc":"The new start time of the event","default":"","type":"timestamp","name":"start","in":"body","_id":"564c95012dc03121001b343c"},{"name":"end","in":"body","_id":"564c95012dc03121001b343b","required":false,"desc":"The new end time of the event","default":"","type":"timestamp"},{"desc":"The new what of the event","default":"","type":"string","name":"what","in":"body","_id":"564c95012dc03121001b3439","required":false},{"default":"","type":"string","name":"where","in":"body","_id":"564c95012dc03121001b3438","required":false,"desc":"The new where of the event"},{"required":false,"desc":"List of emails to invite","default":"","type":"array_string","name":"participants","in":"body","_id":"564c95012dc03121001b343a"},{"name":"all_day","in":"body","_id":"56685e8232fe4e0d0084f49d","required":false,"desc":"Is all day event?","default":"false","type":"boolean"}],"results":{"codes":[{"status":204,"language":"json","code":"","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/events/:id"},"isReference":true,"project":"550ada512188a71900453199","user":"550ada38cd78a42300ddf508","createdAt":"2015-11-18T15:10:57.376Z","editedParams":true,"excerpt":"","order":3,"updates":[],"parentDoc":null,"slug":"eventsuuid","body":"You can update any of the params in an event by calling this endpoint. \n\nUpdates to events in a Google connected calendar will also be updated on Google and synced back to Timekit.","editedParams2":true,"hidden":false,"link_external":false,"link_url":"","sync_unique":"","version":"550bfb5522ccb01700a79469","next":{"pages":[]},"childrenPages":[]}

put/events/:id


Body Params

start:
timestamp
The new start time of the event
end:
timestamp
The new end time of the event
what:
string
The new what of the event
where:
string
The new where of the event
participants:
array of strings
List of emails to invite
all_day:
booleanfalse
Is all day event?
You can update any of the params in an event by calling this endpoint. Updates to events in a Google connected calendar will also be updated on Google and synced back to Timekit.

Definition

{{ api_url }}{{ page_api_url }}


You can update any of the params in an event by calling this endpoint. Updates to events in a Google connected calendar will also be updated on Google and synced back to Timekit.
{"_id":"55f721cb57015d0d00aaecb1","api":{"params":[{"type":"string","name":"id","in":"body","_id":"55f721cb57015d0d00aaecb2","required":false,"desc":"id of the event","default":"","ref":""}],"results":{"codes":[{"status":200,"language":"json","code":"{}","name":""},{"status":400,"language":"json","code":"{}","name":""}]},"settings":"","url":"/events","auth":"required","method":"delete","examples":{"codes":[]}},"project":"550ada512188a71900453199","type":"delete","updates":[],"user":"550ada38cd78a42300ddf508","category":"55113dab9171e82b00897160","link_url":"","parentDoc":null,"slug":"eventsid","sync_unique":"","createdAt":"2015-09-14T19:36:43.875Z","editedParams2":true,"excerpt":"","order":4,"title":"/events/:id","__v":1,"body":"If the user/resource have connected with their google account then the event will be deleted both on google and in the timekit database. Otherwise the event will just be deleted in the timekit database","editedParams":true,"githubsync":"","hidden":false,"isReference":true,"link_external":false,"version":"550bfb5522ccb01700a79469","next":{"description":"","pages":[]},"childrenPages":[]}

delete/events/:id


Body Params

id:
string
id of the event
If the user/resource have connected with their google account then the event will be deleted both on google and in the timekit database. Otherwise the event will just be deleted in the timekit database

Definition

{{ api_url }}{{ page_api_url }}

Result Format



If the user/resource have connected with their google account then the event will be deleted both on google and in the timekit database. Otherwise the event will just be deleted in the timekit database