Introduction
If not already created, a Developer Account is needed for authentication.
Unauthenticated requests are not allowed.
If modules or apps are to be developed for an existing organization, it is currently not possible to directly link them to this organization. To have modules and apps appear in the App Store for organizations, bookingtime must be contacted. In the future it will be possible to connect apps and modules via a separate key.
If apps or modules were developed before an organization was created, they will appear in the App Store. Take a look at the order of steps of our "How to create your first module" article.
Please note that the Client Credentials Flow must not be used in single page applications (SPAs) and native applications under any circumstances, unless you are using a testing application that is intended to be deleted later. The client secret must be kept confidential and static client secrets could easily be extracted by third parties!
All necessary information on usage and technical details of our specific implementation can be found in our Authentication Documentation.
Overview
Making requests to the bookingtime platform requires that your application is authenticated and authorized to access data. Your application can be authenticated in two ways:
-
App Authentication: bookingtime authorizes your application to access the bookingtime platform.
Using the Client Credentials Flow. -
User Authentication: bookingtime, as well as the user, grant your application permission to access and/or modify data.
Using the Authorization Code Flow.
In both cases, the bookingtime authorization server responds first with an refresh token, which then can be exchanged for an access token:
{
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJleHBpcmVkX3N0b3J5IjoicmVhZ3JvdXAiLCJpYXQiOjE2MjYwNzg1NzgsInN1YiI6InVzZXIxMjM0NTYifQ.2oP0M1Xm7bbkXQz47fuMzOa5qV7yo-dQfxThymfg2PQ",
"token_type": "Bearer",
"expires_in": "<time in s>"
}
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJleHBpcmVkX3N0b3J5IjoicmVhZ3JvdXAiLCJpYXQiOjE2MjYwNzg1NzgsInN1YiI6InVzZXIxMjM0NTYifQ.2oP0M1Xm7bbkXQz47fuMzOa5qV7yo-dQfxThymfg2PQ",
"token_type": "Bearer",
"expires_in": "<time in s>"
}
These tokens are a JSON Web Tokens and their full structure can be seen here. A valid access token allows you to query the bookingtime API:
GET /app/v3/ HTTP/1.1
Host: api.bookingtime.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJleHBpcmVkX3N0b3J5IjoicmVhZ3JvdXAiLCJpYXQiOjE2MjYwNzg1NzgsInN1YiI6InVzZXIxMjM0NTYifQ
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJleHBpcmVkX3N0b3J5IjoicmVhZ3JvdXAiLCJpYXQiOjE2MjYwNzg1NzgsInN1YiI6InVzZXIxMjM0NTYifQ.2oP0M1Xm7bbkXQz47fuMzOa5qV7yo-dQfxThymfg2PQ"
https://api.bookingtime.com/app/v3/
At this point, your request should be authenticated, but your app/user may not be permitted to access a specific endpoint.
Your application must be explicitly allowed to access a specific organization and users have various read and write permissions.
You simply want to try out our API or test possible integrations with your system without too much effort?
In this case, we recommend the usage of the Client Credentials Flow. The Client Credentials Flow is used for machine-to-machine authentication and therefore does not need any user interaction.
After creating a new app in the developer service, you will receive a Client ID and Client Secret, which you can use to authenticate your own app. This gives you access to a demo organization and allows you to use all common functions of the bookingtime system. Only user specific endpoints are not allowed. Please note that this is only a recommendation for prototypes to reduce the implementation complexity. The use of the Client Credential Flow may not be allowed for your use case.
Alternatively, you are free to implement the Authorization Code Flow.
Request access to the API
Register a developer account at the bookingtime developer service.
How to use the App API
In this example, we use the client credentials flow to send a successful request to the bookingtime App API using individual credentials. Requests to the bookingtime Module API work analog to this, but the client secret must be omitted or empty.The following credentials are required:
Client ID | Unique ID of your custom app |
Client Secret | Secret to authenticate your app |
Organization ID | Unique token of your demo organization |
Have your application request authentication
To request a refresh token, an application must make a POST request to the oauth/token
endpoint for a client credentials to token bundle exchange.
Example Request:
POST /oauth/token HTTP/1.1
Host: auth.bookingtime.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJleHBpcmVkX3N0b3J5IjoicmVhZ3JvdXAiLCJpYXQiOjE2MjYwNzg1NzgsInN1YiI6InVzZXIxMjM0NTYifQ.2oP0M1Xm7bbkXQz47fuMzOa5qV7yo-dQfxThymfg2PQ https://api.bookingtime.com/app/v3/
Content-Type: application/json
Content-Length: 77
{"grant_type":"client_credentials", "client_id":"23...YOUR_CLIENT_ID"}
curl -X POST \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJleHBpcmVkX3N0b3J5IjoicmVhZ3JvdXAiLCJpYXQiOjE2MjYwNzg1NzgsInN1YiI6InVzZXIxMjM0NTYifQ.2oP0M1Xm7bbkXQz47fuMzOa5qV7yo-dQfxThymfg2PQ https://api.bookingtime.com/app/v3/" \
-H "Content-Type: application/json" \
-d grant_type=client_credentials \
-d client_id=23...YOUR_CLIENT_ID \
https://auth.bookingtime.com/oauth/token
Example Response:
{
"refresh_token": "eyJhbGc...",
"token_type": "Bearer",
"expires_in": 2592000
}
Exchange refresh token
Exchange the refresh token for an organization specific access token again, send a POST request to the oauth/token
endpoint, but this time with the refresh token and the ID of a organization your app is permitted to access.
Example Request:
POST /oauth/token HTTP/1.1
Host: auth.bookingtime.com
Authorization: Bearer eyJhbGc... https://api.bookingtime.com/app/v3/
Content-Type: application/json
Content-Length: 123
grant_type=refresh_token&client_id=70...YOUR_CLIENT_ID&refresh_token=eyJ0eX...&organization_id=f6123456789101112131415aBCdeFgH
curl -X POST \
-H "Authorization: Bearer eyJhbGc... https://api.bookingtime.com/app/v3/" \
-H "Content-Type: application/json" \
-d grant_type=refresh_token \
-d client_id=70...YOUR_CLIENT_ID \
-d refresh_token=eyJ0eX... \
-d organization_id=f6f6123456789101112131415aBCdeFgH
https://auth.bookingtime.com/oauth/token
Example Response
{
"access_token": "eyJhbGc...",
"token_type": "Bearer",
"expires_in": 300
}
Use your access token to query the bookingtime App API
The received access token is valid for 5 minutes and allows you to make requests to the bookingtime App API endpoints that do not require user authorization such as the Show an Organization endpoint.
Example Request:
GET /app/v3/de/organization/f6123456789101112131415aBCdeFgH/show HTTP/1.1
Host: api.bookingtime.com
Authorization: Bearer eyJhbGc...
curl -X "GET" -H "Authorization: Bearer eyJhbGc..."
https://api.bookingtime.com/app/v3/de/organization/f6123456789101112131415aBCdeFgH/show
Example Response:
{
"messageList": [],
"content": {
"class": "ORGANIZATION",
"id": "f6123456789101112131415aBCdeFgH",
"customId": "123-1",
"timestampAdd": "2023-02-20T19:31:52+01:00",
"timestampEdit": "2025-02-06T00:01:13+01:00",
"contractAccount": {
"class": "CONTRACT_ACCOUNT",
"id": "c4123456789101112131415aBCdeFgH",
"customId": "acme",
"accountNumber": 10000001,
"name": "ACME ContractAccount"
},
"name": "ACME",
"rootOrganizationFlag": false,
"blocked": false,
"notes": "",
"address": {
"class": "INHERITANCE",
"value": {
"class": "ADDRESS",
"name": "ACME",
"extra": "First floor",
"street": "Street 10",
"zip": "12345",
"city": "Hamburg",
"country": "DE",
"geoCoordinates": {
"class": "GEO_COORDINATES",
"latitude": 52.6059747,
"longitude": 8.9841561
}
},
"inheritance": "PARENT_ORGANIZATION",
"result": {
"class": "ADDRESS",
"name": "ACME",
"extra": "",
"street": "Street 10",
"zip": "12345",
"city": "Hamburg",
"country": "DE",
"geoCoordinates": {
"class": "GEO_COORDINATES",
"latitude": 52.6059747,
"longitude": 8.9841561
}
}
},
"telephone": {
"class": "INHERITANCE",
"value": "040/12345678",
"inheritance": "PARENT_ORGANIZATION",
"result": "040/12345678"
},
"fax": {
"class": "INHERITANCE",
"value": "040/12345679",
"inheritance": "PARENT_ORGANIZATION",
"result": "040/12345679"
},
"description": {
"class": "INHERITANCE",
"value": "First sub organization",
"inheritance": "PARENT_ORGANIZATION",
"result": "Die erste Firma aus dem datafixture..."
},
"descriptionI18nList": {
"class": "INHERITANCE",
"value": [],
"inheritance": "PARENT_ORGANIZATION",
"result": [
{"class": "KEY_VALUE", "key": "en", "value": "First organization"}
]
},
"logo": {
"class": "INHERITANCE",
"value": "",
"inheritance": "PARENT_ORGANIZATION",
"result": "https://content.bookingtime.com/image/rO123456789101112131415aBCdeFgH"
},
"imageList": {
"class": "INHERITANCE",
"value": [],
"inheritance": "PARENT_ORGANIZATION",
"result": [
"https://content.bookingtime.com/image/rO12345678910deFgH1112131415aBC",
"https://content.bookingtime.com/image/rOaBCdeFgH123456789101112131415",
"https://content.bookingtime.com/image/rO123456789101112131415aBCdeFgH"
]
},
"email": {
"class": "INHERITANCE",
"value": "info@acme.com",
"inheritance": "PARENT_ORGANIZATION",
"result": "central@acme.com"
},
"websiteList": {
"class": "INHERITANCE",
"value": [
"http://www.acme.de",
"https://www.facebook.com/acme",
"https://www.instagram.com/acme/",
"https://twitter.com/acme",
"https://www.youtube.com/acme",
"https://vimeo.com/acme"
],
"inheritance": "PARENT_ORGANIZATION",
"result": [
"http://www.acme.de",
"https://www.facebook.com/acme",
"https://www.instagram.com/acme/",
"https://twitter.com/acme",
"https://www.youtube.com/acme",
"https://vimeo.com/acme"
]
},
"contactPerson": {
"class": "INHERITANCE",
"value": {
"class": "CONTACT_PERSON",
"gender": "MALE",
"title": "Dr.",
"firstName": "John",
"lastName": "Doe",
"telephone": "040/12345678",
"email": "jd@acme.com",
"mobile": ""
},
"inheritance": "PARENT_ORGANIZATION",
"result": {
"class": "CONTACT_PERSON",
"gender": "MALE",
"title": "Dr.",
"firstName": "John",
"lastName": "Doe",
"telephone": "040/12345678",
"email": "jd@acme.com",
"mobile": ""
}
},
"accessibility": {
"class": "INHERITANCE",
"value": {
"class": "ORGANIZATION_ACCESSIBILITY",
"information": true,
"entry": "PARTIAL",
"signLanguage": true,
"description": ""
},
"inheritance": "PARENT_ORGANIZATION",
"result": {
"class": "ORGANIZATION_ACCESSIBILITY",
"information": true,
"entry": "PARTIAL",
"signLanguage": true,
"description": ""
}
},
"openingHours": {
"class": "INHERITANCE",
"value": {
"class": "OPENING_HOURS",
"monday": ["09:00", "10:00", "12:00", "18:00"],
"tuesday": ["08:00", "18:00"],
"wednesday": ["08:00", "18:00"],
"thursday": ["08:00", "18:00"],
"friday": ["08:00", "18:00"],
"saturday": [],
"sunday": []
},
"inheritance": "PARENT_ORGANIZATION",
"result": {
"class": "OPENING_HOURS",
"monday": ["09:00", "18:00"],
"tuesday": ["09:00", "12:00", "14:00", "20:00"],
"wednesday": ["09:00", "18:00"],
"thursday": ["08:00", "19:00"],
"friday": ["07:00", "18:00"],
"saturday": [],
"sunday": []
}
},
"settings": {
"class": "ORGANIZATION_SETTINGS",
"timeZone": {
"class": "INHERITANCE",
"value": "Europe/Berlin",
"inheritance": "PARENT_ORGANIZATION",
"result": "Europe/Berlin"
},
"currency": {
"class": "INHERITANCE",
"value": "EUR",
"inheritance": "PARENT_ORGANIZATION",
"result": "EUR"
},
"taxRate": {
"class": "INHERITANCE",
"value": 19,
"inheritance": "PARENT_ORGANIZATION",
"result": 19
},
"showPrice": {
"class": "INHERITANCE",
"value": true,
"inheritance": "PARENT_ORGANIZATION",
"result": true
},
"emailReply": {
"class": "INHERITANCE",
"value": "info@acme.com",
"inheritance": "PARENT_ORGANIZATION",
"result": "info@acme.com"
},
"smsSender": {
"class": "INHERITANCE",
"value": "ACME",
"inheritance": "PARENT_ORGANIZATION",
"result": "ACMEroot"
},
"locale": {
"class": "INHERITANCE",
"value": "de-DE",
"inheritance": "PARENT_ORGANIZATION",
"result": "de"
},
"availability": {
"class": "INHERITANCE",
"value": "CUSTOM",
"inheritance": "PARENT_ORGANIZATION",
"result": "OPENING_HOURS"
},
"timeGrid": {
"class": "INHERITANCE",
"value": "CUSTOM",
"inheritance": "PARENT_ORGANIZATION",
"result": "MINUTES_15"
},
"moduleBookingDayEarliest": {
"class": "INHERITANCE",
"value": 0,
"inheritance": "PARENT_ORGANIZATION",
"result": 0
},
"moduleBookingDayLatest": {
"class": "INHERITANCE",
"value": 999,
"inheritance": "PARENT_ORGANIZATION",
"result": 14
},
"moduleBookingLeadTime": {
"class": "INHERITANCE",
"value": 0,
"inheritance": "PARENT_ORGANIZATION",
"result": 120
},
"externalCalendarContentCustomer": {
"class": "INHERITANCE",
"value": "[ORGANIZATION_NAME] [BOOKING_TEMPLATE_PUBLIC_NAME]",
"inheritance": "PARENT_ORGANIZATION",
"result": "[ORGANIZATION_NAME] [BOOKING_TEMPLATE_PUBLIC_NAME]"
},
"externalCalendarContentCustomerI18nList": {
"class": "INHERITANCE",
"value": [],
"inheritance": "PARENT_ORGANIZATION",
"result": [
{
"class": "KEY_VALUE",
"key": "en",
"value": "[ORGANIZATION_NAME] [BOOKING_TEMPLATE_PUBLIC_NAME]"
}
]
},
"externalCalendarContentStaff": {
"class": "INHERITANCE",
"value": "[CUSTOMER_FULL_NAME] test& [BOOKING_TEMPLATE_NAME] [APPOINTMENT_NOTES]",
"inheritance": "PARENT_ORGANIZATION",
"result": "[CUSTOMER_FULL_NAME] [BOOKING_TEMPLATE_NAME] [APPOINTMENT_NOTES]"
},
"moduleMultiFactorProtection": {
"class": "INHERITANCE",
"value": "OFF",
"inheritance": "PARENT_ORGANIZATION",
"result": "EMAIL"
},
"customerAddressRequired": {
"class": "INHERITANCE",
"value": false,
"inheritance": "PARENT_ORGANIZATION",
"result": false
},
"customerEmailRequired": {
"class": "INHERITANCE",
"value": false,
"inheritance": "PARENT_ORGANIZATION",
"result": false
},
"customerMobileRequired": {
"class": "INHERITANCE",
"value": false,
"inheritance": "PARENT_ORGANIZATION",
"result": false
},
"synchronizationServer": {
"class": "INHERITANCE",
"value": null,
"inheritance": "OFF",
"result": null
},
"emailTemplateList": [
{
"class": "EMAIL_TEMPLATE_SHORT",
"id": "46123456789101112131415aBCdeFgH",
"customId": "",
"name": "Aftersale E-Mail",
"organizationId": "f6123456789101112131415aBCdeFgH"
},
{
"class": "EMAIL_TEMPLATE_SHORT",
"id": "46LH83IO0DWLRAY5eBllM8NhuZOLwRoH",
"customId": "abcd",
"name": "E-Mail Terminabsage an den Kunden",
"organizationId": "f6123456789101112131415aBCdeFgH"
},
{
"class": "EMAIL_TEMPLATE_SHORT",
"id": "46CycLFhuFbAprDp0hD1hojstwDuLUBp",
"customId": "",
"name": "E-Mail Terminabsage an den Mitarbeiter",
"organizationId": "f6123456789101112131415aBCdeFgH"
},
{
"class": "EMAIL_TEMPLATE_SHORT",
"id": "46a6NWcBgly2Wyl2e5sTXF0joar3KOdV",
"customId": "1234",
"name": "E-Mail Terminbestätigung an den Kunden",
"organizationId": "f6123456789101112131415aBCdeFgH"
},
{
"class": "EMAIL_TEMPLATE_SHORT",
"id": "4619KvNIewpVeFqc6kopCtOYHaq5Oagz",
"customId": "12345",
"name": "E-Mail Terminbestätigung an den Mitarbeiter",
"organizationId": "f6123456789101112131415aBCdeFgH"
},
{
"class": "EMAIL_TEMPLATE_SHORT",
"id": "46123456789101112131415aBCdeFgH",
"customId": "",
"name": "E-Mail Terminerinnerung an den Kunden",
"organizationId": "f6123456789101112131415aBCdeFgH"
},
{
"class": "EMAIL_TEMPLATE_SHORT",
"id": "46123456789101112131415aBCdeFgH",
"customId": "",
"name": "E-Mail Terminverschiebung",
"organizationId": "f6123456789101112131415aBCdeFgH"
}
],
"smsTemplateList": [
{
"class": "SMS_TEMPLATE_SHORT",
"id": "6G123456789101112131415aBCdeFgH",
"customId": "",
"name": "After customer-start",
"organizationId": "f6123456789101112131415aBCdeFgH"
}
],
"extraFieldList": [
{
"class": "EXTRA_FIELD_SHORT",
"id": "l1123456789101112131415aBCdeFgH",
"customId": "",
"name": "Customer Size",
"type": "CHECKBOX",
"organizationId": "f6123456789101112131415aBCdeFgH"
}
]
},
"sector": {
"class": "INHERITANCE",
"value": "01ab",
"inheritance": "PARENT_ORGANIZATION",
"result": "01ab"
},
"licenseConfigList": [
{
"class": "LICENSE_CONFIG_SHORT",
"id": "lC123456789101112131415aBCdeFgH",
"customId": "test2",
"licenseId": "1l123456789101112131415aBCdeFgH",
"licenseName": "Default license",
"organizationId": "f6123456789101112131415aBCdeFgH"
}
],
"additionalData": {
"testKey": ["testvalue1", "testvalue2"],
"bktest_color": ["#123456"]
},
"contingent": {
"class": "CONTINGENT",
"employeeLicense": {
"class": "EMPLOYEE_LICENSE",
"inclusive": 20,
"paid": 0,
"used": 5,
"unused": 15,
"total": 20,
"price": 2
},
"organizationLicense": {
"class": "ORGANIZATION_LICENSE",
"inclusive": 0,
"paid": 1,
"used": 1,
"unused": 0,
"total": 1,
"price": 0
},
"resourceLicense": {
"class": "RESOURCE_LICENSE",
"inclusive": 10,
"paid": 0,
"used": 5,
"unused": 5,
"total": 10,
"price": 2
},
"synchronizationLicense": {
"class": "SYNCHRONIZATION_LICENSE",
"inclusive": 5,
"paid": 0,
"used": 1,
"unused": 4,
"total": 5,
"price": 0
},
"sms": 93
},
"trialPeriod": {
"class": "TRIAL_PERIOD",
"timestampStart": null,
"timestampEnd": null,
"duration": null
}
}
}
Add your first customer
Now we want to add a new customer named John Doe to your organization. For this we will use the Add Customer endpoint and pass the data in application/json format.
Example Request:
POST /app/v3/de/organization/f6123456789101112131415aBCdeFgH/customer/add HTTP/1.1
Host: api.bookingtime.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJleHBpcmVkX3N0b3J5IjoicmVhZ3JvdXAiLCJpYXQiOjE2MjYwNzg1NzgsInN1YiI6InVzZXIxMjM0NTYifQ.2oP0M1Xm7bbkXQz47fuMzOa5qV7yo-dQfxThymfg2PQ
Content-Type: application/json
Content-Length: 38
{"firstName":"John", "lastName":"Doe"}
curl -X "POST" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJleHBpcmVkX3N0b3J5IjoicmVhZ3JvdXAiLCJpYXQiOjE2MjYwNzg1NzgsInN1YiI6InVzZXIxMjM0NTYifQ.2oP0M1Xm7bbkXQz47fuMzOa5qV7yo-dQfxThymfg2PQ" "Content-Type: application/json"
-d '{"firstName":"John", "lastName":"Doe"}'
https://api.bookingtime.com/app/v3/de/organization/f6123456789101112131415aBCdeFgH/customer/add
Example Response:
{
"class": "CUSTOMER_SHORT",
"id": "d3...",
"customId": "",
"firstName": "John",
"lastName": "Doe",
"organizationId": "f6123456789101112131415aBCdeFgH"
},
Comments
0 comments
Please sign in to leave a comment.