timekit-sdk
Version:
JavaScript SDK for the Timekit API (timekit.io)
367 lines (290 loc) • 12.5 kB
Markdown
# Timekit JS SDK
[](https://circleci.com/gh/timekit-io/js-sdk)
[](https://github.com/timekit-io/js-sdk)
[**Releases & changelog**](https://github.com/timekit-io/js-sdk/releases)
Make API calls to Timekit with our easy-to-use JavaScript SDK. It supports all our endpoints as documented on [https://reference.timekit.io/](https://reference.timekit.io/).
Visit [timekit.io](http://timekit.io) to learn more and don't hesitate to contact Lasse Boisen Andersen ([la@timekit.io](mailto:la@timekit.io) or create an Issue) for questions. PR's are more than welcome!
Features:
- Supports API auth with both app keys and resource keys
- Returns ES6/A+ style promises
- Works in both node.js and in the browser (>=IE8 and evergreen)
- Supports custom timestamp formats and timezones
## Dependencies
The following libraries are bundled together with the SDK:
- [axios](https://github.com/mzabriskie/axios) - a promise-based HTTP client for the browser (using [XMLHttpRequests](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)) and node.js (using [http](http://nodejs.org/api/http.html))
- [base64](https://github.com/mathiasbynens/base64) - a robust base64 encoder/decoder, used for basic auth headers
- [humps](https://github.com/domchristie/humps) - easy conversion from camelCase to snake_case and vice versa
## Installation
The library is hosted on NPM, so you can simply go:
`npm install timekit-sdk --save`
## Module loading
The SDK is UMD (Universal Module Definition) compatible, which means that it can be loaded in various module formats across both browsers and server.
*Note: Use plain or minified builds in `/dist` when using in browser. In node, `/src/timekit.js` will be used through npm (or reference it manually in your require)*
**ES6 module**
```javascript
import timekit from 'timekit-sdk'
console.log(timekit);
```
**AMD (with e.g. require.js)**
```javascript
require(['timekit-sdk'], function(timekit) {
console.log(timekit);
});
```
**CommonJS2 (in e.g. node.js)**
```javascript
var timekit = require('timekit-sdk');
console.log(timekit);
```
**As a global variable (in browsers)**
```javascript
<script src="timekit-sdk.js"></script>
<script>
console.log(timekit);
</script>
```
See `/examples` for implementation examples.
## Authentication
### App key
*Only for server-side integrations!*
With app keys, your capabilities are scoped on an app-level which mean that you can access data (e.g. bookings) across all resources. It's essential that you only use this for server-side integrations as the key grants full access to your whole timekit app data.
```javascript
timekit.configure({
appKey: 'live_api_key_4cY2KWMggw95mAdx51eYUO2CyIWI2xup'
})
```
Your app key can be found in the Timekit admin panel (https://admin.timekit.io)
### Resource keys
*For client-side integrations!*
Resource keys are scoped by the resource and the data that they have access to. The primary use-case is together with our booking.js widget that only acts as a single resource at a time.
Resource keys needs to be accompanied by the resource's email and the app attribute. Note that two types of keys exist: `server-token` and `client-token`, where only the latter should be used. Please refer to the [API reference](https://developers.timekit.io/reference#credentials).
```javascript
timekit.configure({
app: 'back-to-the-future',
resourceEmail: 'marty.mcfly .io',
resourceKey: '4cY2KWMggw95mAdx51eYUO2CyIWI2xup'
})
```
🚨 **Important!** Resource keys are being phased out as a supported authentication mechanism. We encourage you to use app keys for new Timekit integrations.
## Usage (init)
The only required configuration is that you set the "app" key to your registered app slug on Timekit.
Here's all the available options:
```javascript
// Overwrites default config with supplied object, possible keys with default values below
timekit.configure({
apiBaseUrl: 'https://api.timekit.io/', // API endpoint (do not change)
apiVersion: 'v2', // version of API to call (do not change)
inputTimestampFormat: 'Y-m-d h:ia', // default timestamp format that you supply
outputTimestampFormat: 'Y-m-d h:ia', // default timestamp format that you want the API to return
timezone: 'Europe/Copenhagen', // override user's timezone for custom formatted timestamps in another timezone
convertResponseToCamelcase: false, // should keys in JSON response automatically be converted from snake_case to camelCase?
convertRequestToSnakecase: true, // should keys in JSON requests automatically be converted from camelCase to snake_case?
autoFlattenResponse: true // if you keep this set to true, then responses with a "data" key will automatically be flattened to response.data (otherwise you need to access response.data.data). Pagination meta data can be found on response.metaData)
});
// Returns current config object
timekit.getConfig();
```
## Usage (endpoints)
All the Timekit API endpoints are supported as methods. For endpoints taking parameters/data, the method argument should be an object with keys named as referenced in the docs - see: https://developers.timekit.io/reference/
If you supply keys as camelCased, they will automatically be converted to snake_case for you. Responses can also be converted to camelCase automatically if you set the config variable `convertResponseToCamelcase` to true.
Endpoints/methods:
```javascript
// App endpoints
timekit.getApp()
// Resource endpoints
timekit.getResources()
timekit.getResource({ id })
timekit.createResource({ ... })
timekit.updateResource({ id, ... })
timekit.resetResourcePassword({ ... })
timekit.getResourceTimezone({ email })
// FindTime endpoints
timekit.findTime({ ... })
timekit.findTimeBulk({ ... })
timekit.findTimeTeam({ ... })
// Availability endpoints
timekit.fetchAvailability({ ... })
timekit.fetchUnAvailableSlots({ ... })
timekit.fetchAvailabilityDates({ ... })
timekit.fetchAvailabilityCounts({ ... })
// Booking endpoints
timekit.getBookings()
timekit.getBooking({ id })
timekit.createBooking({ ... })
timekit.createBookingsBulk({ ... })
timekit.updateBooking({ id, action, ... })
timekit.updateBookingsBulk({ ... })
timekit.deleteBooking({ id })
timekit.getGroupBookings()
timekit.getGroupBooking({ id })
timekit.rescheduleBooking({ id, ... })
// Account endpoints
timekit.getAccounts()
timekit.accountGoogleSignup({ callback }, shouldAutoRedirect)
timekit.accountGoogleSync()
timekit.accountMicrosoftSignup({ callback }, shouldAutoRedirect)
timekit.accountMicrosoftSync()
// Calendar endpoints
timekit.getCalendars()
timekit.getCalendar({ id })
timekit.createCalendar({ ... })
timekit.updateCalendar({ id, ... })
timekit.deleteCalendar({ id })
// Project endpoints
timekit.getProjects()
timekit.getProject({ id })
timekit.getHostedProject({ slug })
timekit.getEmbedProject({ id })
timekit.createProject({ ... })
timekit.updateProject({ id, ... })
timekit.deleteProject({ id })
timekit.getProjectResources({ id })
timekit.addProjectResource({ id, ... })
timekit.setProjectResources({ id, resources })
timekit.removeProjectResource({ id, resourceId })
// Event endpoints
timekit.getEvents({ ... })
timekit.getEvent({ id })
timekit.createEvent({ ... })
timekit.updateEvent({ id, ... })
timekit.deleteEvent({ id })
// Service endpoints
timekit.getServices({ ... })
timekit.getService({ id })
timekit.createService({ ... })
timekit.updateService({ id, ... })
timekit.deleteService({ id })
// Location endpoints
timekit.getLocations({ ... })
timekit.getLocation({ id })
timekit.createLocation({ ... })
timekit.updateLocation({ id, ... })
timekit.deleteLocation({ id })
// service location related endpoints
timekit.getServiceProjects(id)
timekit.getLocationProjects(id)
timekit.getLocationServiceProjects(locationUuid, serviceUuid)
// email template related endpoints
timekit.getEmailTemplates()
timekit.getEmailTemplate(slug)
timekit.updateEmailTemplate({ slug, ... })
// booking reservation
timekit.reserveBooking({ ... })
timekit.extendReservedBooking({ ... })
// Auth endpoints (Note: only used to fetch a resource key)
timekit.auth({ ... })
// Credential endpoints (Note: only used to manage resource keys)
timekit.getCredentials()
timekit.createCredential({ ... })
timekit.deleteCredential({ id })
```
Request example:
```javascript
// Using promises
timekit.createBooking({
resource_id: 'd187d6e0-d6cb-409a-ae60-45a8fd0ec879',
graph: 'confirm_decline',
start: '1955-11-12T21:30:00-07:00',
end: '1955-11-12T22:15:00-07:00',
what: 'Catch the lightning',
where: 'Courthouse, Hill Valley, CA 95420, USA',
description: 'The lightning strikes at 10:04 PM exactly! I need you to be there Doc!',
customer: {
name: 'Marty McFly',
email: 'marty.mcfly .io',
phone: '(916) 555-4385',
voip: 'McFly',
timezone: 'America/Los_Angeles'
}
}).then(function(response){
console.log(response);
}).catch(function(response){
console.log(response);
});
// Using async/await
const response = await timekit.createBooking({ ... })
```
Response example:
```javascript
{
// data is the response that was provided by the server
data: {},
// status is the HTTP status code from the server response
status: 200,
// statusText is the HTTP status message from the server response
statusText: 'OK',
// headers the headers that the server responded with
headers: {},
// config is the config that was provided to `axios` for the request
config: {}
}
```
## Usage (low-level API)
If you, for some reason, would like direct access to axios's request API, you can call the `timekit.makeRequest()` method directly. We'll still set the correct config headers, base url and includes, but otherwise it supports all the settings that [axios](https://github.com/mzabriskie/axios) does.
Example:
```javascript
timekit.makeRequest({
url: '/bookings',
method: 'post',
data: {
key: 'value'
},
timeout: 1000
}).then(function(response){
console.log(response);
}).catch(function(response){
console.log(response);
});
```
## Usage (carry)
If you want to inject specific params/query string or data into the next API request, you can use the `carry` method. It's handy for e.g. filtering result (`search`) or adding pagination (`limit`).
Example:
```javascript
timekit
.carry({
params: {
search: 'graph:confirm_decline',
limit: 10
}
})
.getBookings()
.then(function(response) {
// Response is filtered by the search query and limited to only 10 items
});
```
## Usage (dynamic includes)
The Timekit API have support for [dynamically including related models](https://reference.timekit.io/reference#dynamic-includes) (aka. expand objects). We supports this functionality by providing a chainable/fluent method called `.include()` that can be called right before a request.
The method takes unlimited string arguments, with each one being a model that you want included in the response. For nested data (e.g. events grouped by calendar), use the dot notation to dig into relations, like `calender.events`.
Example:
```javascript
timekit
.include('calendars.events', 'users')
.getUserInfo()
.then(function(response) {
// Response contains JSON data with nested info on the user's calendars, events and meetings
});
```
This is super powerful because it means that you can avoid unnecessary extra requests compared to fetching each resource sequentially.
## Building from source
We use [webpack](http://webpack.github.io) for packaging the library as a module. To build the source files in `/src` to `/dist`, run:
```bash
# install dev dependencies
npm install
# build plain
webpack
# build minified
webpack --config webpack.config.min.js
```
## Running tests
We use [jasmine](http://jasmine.github.io) + [karma](http://karma-runner.github.io/) for unit testing, which works together with webpack.
To run the test suite, simply do:
```bash
# install dev dependencies
npm install
# install karma as global
npm install -g karma
# start karma and run
karma start
```
## Roadmap/todos
See [Issues](https://github.com/timekit-io/js-sdk/issues) for feature requests, bugs etc.