Info
Welcome to the generated API reference. Get Postman Collection
This API is being developed constantly with more endpoints being added regularly.
Authentication
All endpoints require authentication via the Authorization: Bearer {token}
header. There are 2 ways to get the token:
Personal Access Tokens
- Log in to your EasyPractice account (or create a new account)
- Go to the Apps page and activate the API app.
- Go to the API Settings page
- In the Personal Access Tokens section click on the Create New Token button to generate a new token.
- Copy the new generated token. You will NOT be able to view it again, so keep it safe. In case you lose it, you can generate as many new tokens as you'd like.
- Add an
Authorization
header to your requests with the value ofBearer {token}
where {token} is your token you copied earlier.
OAuth2 flow
We also support the standard OAuth2 flow for authenticating requests. Your app will be able to "Request access to EasyPractice", where the user will be able to either Authorize or Deny the request. This is a much more user-friendly approach, but requires more set up in advance.
If you would like to set up OAuth2 flow with our API, please get in touch with us at support@easypractice.net.
Bookings
List bookings
Requires authentication
Returns all of user's bookings. Use the filter options provided to narrow down the results. For example: GET api/v1/bookings?start=2019-06-15&order_by_date=asc
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->get("api/v1/bookings", [
'headers' => [
"Authorization" => "Bearer {token}",
],
'query' => [
"start" => "2019-03-25",
"end" => "2019-03-25",
"client_id" => "54347",
"calendar_id" => "54347",
"product_id" => "54347",
"status" => "absent",
"order_by_date" => "asc",
"page_size" => "20",
"page" => "4",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X GET -G "https://system.easypractice.net/api/v1/bookings" \
-H "Authorization: Bearer {token}"
const url = new URL("https://system.easypractice.net/api/v1/bookings");
let params = {
"start": "2019-03-25",
"end": "2019-03-25",
"client_id": "54347",
"calendar_id": "54347",
"product_id": "54347",
"status": "absent",
"order_by_date": "asc",
"page_size": "20",
"page": "4",
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
let headers = {
"Authorization": "Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
fetch(url, {
method: "GET",
headers: headers,
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"data": [
{
"id": 1,
"start": "2019-06-15T16:25:00+02:00",
"start_formatted": "Saturday 15 June 2019, 16:25",
"end": "2019-06-15T17:15:00+02:00",
"end_formatted": "Saturday 15 June 2019, 17:15",
"calendar_id": 167,
"calendar_name": "Main calendar",
"type": "client_booking",
"status": "finished",
"heading": "",
"recurring": null,
"until": null,
"client_id": 1348,
"client_name": "John Smith",
"notify_email": 0,
"notify_phone": 0,
"products": [
{
"id": 125,
"name": "Main service"
}
]
},
{
"id": 2,
"start": "2019-09-30T17:55:00+02:00",
"start_formatted": "Monday 30 September 2019, 17:55",
"end": "2019-09-30T21:30:00+02:00",
"end_formatted": "Monday 30 September 2019, 21:30",
"calendar_id": 173,
"calendar_name": "201",
"type": "Client appointment",
"status": "finished",
"heading": "",
"recurring": null,
"until": null,
"client_id": 648,
"client_name": "Mary Williams",
"notify_email": 1,
"notify_phone": 0,
"products": [
{
"id": 125,
"name": "Main service",
"addons": [
{
"id": 434,
"name": "Extra time"
}
]
},
{
"id": 264,
"name": "Other service"
}
]
}
],
"links": {
"...": "..."
},
"meta": {
"...": "..."
}
}
HTTP Request
GET api/v1/bookings
Query Parameters
Parameter | Status | Description |
---|---|---|
start | optional | Return only the bookings scheduled on or after the given date. |
end | optional | Return only the bookings scheduled on or before the given date. |
client_id | optional | Return only bookings belonging to this client ID. |
calendar_id | optional | Return only bookings belonging to this calendar ID. |
product_id | optional | Return only bookings belonging to this product ID. |
status | optional | Return only booking with the given status (must have "Appointment Status" app active). |
order_by_date | optional | =[asc|desc] Order results by date. |
page_size | optional | (default: 10) The number of items per page. |
page | optional | (default: 1) The page number. |
Create booking
Requires authentication
Creates a new booking with the given data.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->post("api/v1/bookings", [
'headers' => [
"Authorization" => "Bearer {token}",
"Content-Type" => "application/json",
],
'json' => [
"start" => "2019-03-25T10:00:00+02:00",
"end" => "2019-03-25T10:00:00+02:00",
"calendar_id" => 54347,
"type" => "client_booking",
"status" => "not_started",
"heading" => "New skill course",
"notes" => "First time for this client",
"recurring" => "daily",
"until" => "2019-03-28",
"client_id" => 1594,
"send_receipt" => true,
"send_phone_receipt" => false,
"notify_email" => true,
"notify_phone" => false,
"products" => [
[
"id" => 1574,
],
[
"id" => 2164,
"addons" => [
[
"id" => 434,
],
],
],
],
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X POST "https://system.easypractice.net/api/v1/bookings" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"start":"2019-03-25T10:00:00+02:00","end":"2019-03-25T10:00:00+02:00","calendar_id":54347,"type":"client_booking","status":"not_started","heading":"New skill course","notes":"First time for this client","recurring":"daily","until":"2019-03-28","client_id":1594,"send_receipt":1,"send_phone_receipt":false,"notify_email":1,"notify_phone":false,"products":[{"id":1574},{"id":2164,"addons":[{"id":434}]}]}'
const url = new URL("https://system.easypractice.net/api/v1/bookings");
let headers = {
"Authorization": "Bearer {token}",
"Content-Type": "application/json",
"Accept": "application/json",
}
let body = {
"start": "2019-03-25T10:00:00+02:00",
"end": "2019-03-25T10:00:00+02:00",
"calendar_id": 54347,
"type": "client_booking",
"status": "not_started",
"heading": "New skill course",
"notes": "First time for this client",
"recurring": "daily",
"until": "2019-03-28",
"client_id": 1594,
"send_receipt": 1,
"send_phone_receipt": false,
"notify_email": 1,
"notify_phone": false,
"products": [
{
"id": 1574
},
{
"id": 2164,
"addons": [
{
"id": 434
}
]
}
]
}
fetch(url, {
method: "POST",
headers: headers,
body: body
})
.then(response => response.json())
.then(json => console.log(json));
Example response (201):
{
"message": "Created",
"data": {
"id": 1,
"start": "2019-06-15T16:25:00+02:00",
"start_formatted": "Saturday 15 June 2019, 16:25",
"end": "2019-06-15T17:15:00+02:00",
"end_formatted": "Saturday 15 June 2019, 17:15",
"calendar_id": 167,
"calendar_name": "Main calendar",
"type": "client_booking",
"status": "finished",
"heading": "",
"recurring": null,
"until": null,
"client_id": 1348,
"client_name": "John Smith",
"notify_email": 0,
"notify_phone": 0,
"products": [
{
"id": 125,
"name": "Main service",
"addons": [
{
"id": 434,
"name": "Extra time"
}
]
}
]
}
}
Example response (422):
{
"error": {
"message": "The given data is invalid",
"status_code": 422
},
"data": {
"name": [
"The Name field is required."
]
}
}
HTTP Request
POST api/v1/bookings
Body Parameters
Parameter | Type | Status | Description |
---|---|---|---|
start | date_format:Y-m-d\TH:i:sP | required | The start date for the appointment in the full ISO 8601 format (e.g. 2019-10-30T08:50:31+00:00). |
end | date_format:Y-m-d\TH:i:sP | required | The end date for the appointment in the full ISO 8601 format (e.g. 2019-10-30T08:50:31+00:00). |
calendar_id | integer | required | The calendar ID associated to the appointment. |
type | string | required | The appointment type =['other_booking', 'close_online_booking', 'client_booking']. |
status | string | optional | The status of the appointment. Must have the "Appointment Status" app enabled. |
heading | string | optional | The appointment title (It's required only for 'other_booking' type). |
notes | string | optional | The appointment additional notes. |
recurring | string | optional | How often this appointment is repeated =[false, 'daily', 'weekly', 'every_other_week'] (It's required for 'other_booking' and 'close_online_booking' types). |
until | date_format:Y-m-d | optional | Until what date this appointment is repeated (It's required if recurring field is different than false). |
client_id | integer | optional | The client ID associated to the appointment (It's required for 'client_booking' type). |
send_receipt | boolean | optional | Should we send the confirmation email straight away? Client must have a valid email address. |
send_phone_receipt | boolean | optional | Should we send the confirmation SMS straight away? Client must have a valid phone number. |
notify_email | boolean | optional | Should we notify the client by email. |
notify_phone | boolean | optional | Should we notify the client by SMS. |
products | array | optional | The products associated to the appointment (It's required for 'client_booking' type). |
Show booking
Requires authentication
Returns the booking data for a given ID.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->get("api/v1/bookings/1", [
'headers' => [
"Authorization" => "Bearer {token}",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X GET -G "https://system.easypractice.net/api/v1/bookings/1" \
-H "Authorization: Bearer {token}"
const url = new URL("https://system.easypractice.net/api/v1/bookings/1");
let headers = {
"Authorization": "Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
fetch(url, {
method: "GET",
headers: headers,
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"id": 1,
"start": "2019-06-15T16:25:00+02:00",
"start_formatted": "Saturday 15 June 2019, 16:25",
"end": "2019-06-15T17:15:00+02:00",
"end_formatted": "Saturday 15 June 2019, 17:15",
"calendar_id": 167,
"calendar_name": "Main calendar",
"type": "client_booking",
"status": "finished",
"heading": "",
"recurring": null,
"until": null,
"client_id": 1348,
"client_name": "John Smith",
"notify_email": 0,
"notify_phone": 0,
"products": [
{
"id": 125,
"name": "Main service",
"addons": [
{
"id": 434,
"name": "Extra time"
}
]
}
]
}
Example response (404):
{
"error": {
"message": "Not Found",
"status_code": 404
}
}
HTTP Request
GET api/v1/bookings/{booking}
Update booking
Requires authentication
Updates the booking.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->put("api/v1/bookings/1", [
'headers' => [
"Authorization" => "Bearer {token}",
"Content-Type" => "application/json",
],
'json' => [
"start" => "2019-03-25T10:00:00+02:00",
"end" => "2019-03-25T10:00:00+02:00",
"calendar_id" => 54347,
"status" => "finished",
"heading" => "New skill course",
"notes" => "First time for this client",
"recurring" => "daily",
"until" => "2019-03-28",
"client_id" => 1594,
"notify_email" => true,
"notify_phone" => false,
"products" => [
[
"id" => 1574,
],
[
"id" => 2164,
"addons" => [
[
"id" => 434,
],
],
],
],
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X PUT "https://system.easypractice.net/api/v1/bookings/1" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"start":"2019-03-25T10:00:00+02:00","end":"2019-03-25T10:00:00+02:00","calendar_id":54347,"status":"finished","heading":"New skill course","notes":"First time for this client","recurring":"daily","until":"2019-03-28","client_id":1594,"notify_email":1,"notify_phone":false,"products":[{"id":1574},{"id":2164,"addons":[{"id":434}]}]}'
const url = new URL("https://system.easypractice.net/api/v1/bookings/1");
let headers = {
"Authorization": "Bearer {token}",
"Content-Type": "application/json",
"Accept": "application/json",
}
let body = {
"start": "2019-03-25T10:00:00+02:00",
"end": "2019-03-25T10:00:00+02:00",
"calendar_id": 54347,
"status": "finished",
"heading": "New skill course",
"notes": "First time for this client",
"recurring": "daily",
"until": "2019-03-28",
"client_id": 1594,
"notify_email": 1,
"notify_phone": false,
"products": [
{
"id": 1574
},
{
"id": 2164,
"addons": [
{
"id": 434
}
]
}
]
}
fetch(url, {
method: "PUT",
headers: headers,
body: body
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"message": "Updated",
"data": {
"id": 1,
"start": "2019-06-15T16:25:00+02:00",
"start_formatted": "Saturday 15 June 2019, 16:25",
"end": "2019-06-15T17:15:00+02:00",
"end_formatted": "Saturday 15 June 2019, 17:15",
"calendar_id": 167,
"calendar_name": "Main calendar",
"type": "client_booking",
"status": "finished",
"heading": "",
"recurring": null,
"until": null,
"client_id": 1348,
"client_name": "John Smith",
"notify_email": 0,
"notify_phone": 0,
"products": [
{
"id": 125,
"name": "Main service",
"addons": [
{
"id": 434,
"name": "Extra time"
}
]
}
]
}
}
Example response (422):
{
"error": {
"message": "The given data is invalid",
"status_code": 422
},
"data": {
"name": [
"The Name field is required."
]
}
}
HTTP Request
PUT api/v1/bookings/{booking}
PATCH api/v1/bookings/{booking}
Body Parameters
Parameter | Type | Status | Description |
---|---|---|---|
start | date_format:Y-m-d\TH:i:sP | optional | The start date for the appointment in the full ISO 8601 format (e.g. 2019-10-30T08:50:31+00:00). |
end | date_format:Y-m-d\TH:i:sP | optional | The end date for the appointment in the full ISO 8601 format (e.g. 2019-10-30T08:50:31+00:00). |
calendar_id | integer | optional | The calendar ID associated to the appointment. |
status | string | optional | The status of the appointment. Must have the "Appointment Status" app enabled. |
heading | string | optional | The appointment heading for 'other_booking' type. |
notes | string | optional | The appointment additional notes. |
recurring | string | optional | How often this appointment is repeated =[false, 'daily', 'weekly', 'every_other_week'] (It's required for 'other_booking' and 'close_online_booking' types). |
until | date_format:Y-m-d | optional | Until what date this appointment is repeated (It's required if recurring field is different than false). |
client_id | integer | optional | The client ID associated to the appointment. |
notify_email | boolean | optional | Should we notify the client by email. |
notify_phone | boolean | optional | Should we notify the client by SMS. |
products | array | optional | The products associated to the appointment. |
Delete booking
Requires authentication
Deletes the booking.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->delete("api/v1/bookings/1", [
'headers' => [
"Authorization" => "Bearer {token}",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X DELETE "https://system.easypractice.net/api/v1/bookings/1" \
-H "Authorization: Bearer {token}"
const url = new URL("https://system.easypractice.net/api/v1/bookings/1");
let headers = {
"Authorization": "Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
fetch(url, {
method: "DELETE",
headers: headers,
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"message": "Deleted"
}
HTTP Request
DELETE api/v1/bookings/{booking}
Clients
List clients
Requires authentication
Returns all of user's clients. Use the filter options provided to narrow down the results. For example: GET api/v1/clients?hasEmail&email=asc
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->get("api/v1/clients", [
'headers' => [
"Authorization" => "Bearer {token}",
],
'query' => [
"active" => "1",
"inactive" => "1",
"has_email" => "1",
"has_phone" => "1",
"cpr" => "1205001234",
"tag_id" => "54347",
"order_by_name" => "asc",
"order_by_created" => "desc",
"order_by_email" => "asc",
"page_size" => "20",
"page" => "4",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X GET -G "https://system.easypractice.net/api/v1/clients" \
-H "Authorization: Bearer {token}"
const url = new URL("https://system.easypractice.net/api/v1/clients");
let params = {
"active": "1",
"inactive": "1",
"has_email": "1",
"has_phone": "1",
"cpr": "1205001234",
"tag_id": "54347",
"order_by_name": "asc",
"order_by_created": "desc",
"order_by_email": "asc",
"page_size": "20",
"page": "4",
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
let headers = {
"Authorization": "Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
fetch(url, {
method: "GET",
headers: headers,
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"data": [
{
"id": 1,
"name": "John Smith",
"email": "john@mydomain.dk",
"phone": "61175736",
"address": "159 Bailey Brooks",
"zip": "W10 6DY",
"city": "Copenhagen",
"cpr": "1598431234",
"notes": "Notes about John",
"profile_image_url": "https:\/\/www.gravatar.com\/avatar\/5ea799d8476cbe0b1965c39e7c7dbd99?d=mm&s=200",
"created_at": "2019-04-16 11:54:42",
"tags": []
},
{
"id": 2,
"name": "Mary Williams",
"email": "m.williams@mycompany.dk",
"phone": "43612915",
"address": "3 Mike Common",
"zip": "NG34 9HJ",
"city": "Copenhagen",
"cpr": "3574261234",
"notes": "",
"profile_image_url": "https:\/\/www.gravatar.com\/avatar\/5ea799d8476cbe0b1965c39e7c7dbd99?d=mm&s=200",
"created_at": "2019-04-20 08:14:21",
"tags": []
}
],
"links": {
"...": "..."
},
"meta": {
"...": "..."
}
}
HTTP Request
GET api/v1/clients
Query Parameters
Parameter | Status | Description |
---|---|---|
active | optional | Return only the active clients. |
inactive | optional | Return only the inactive clients. |
has_email | optional | Return only the clients with an email. |
has_phone | optional | Return only the clients with phone number. |
cpr | optional | Return only the clients with a given CPR number. |
tag_id | optional | Return only clients belonging to this tag ID. |
order_by_name | optional | =[asc|desc] Order results by name. |
order_by_created | optional | =[asc|desc] Order results by creation date. |
order_by_email | optional | =[asc|desc] Order results by email. |
page_size | optional | (default: 10) The number of items per page. |
page | optional | (default: 1) The page number. |
Create client
Requires authentication
Creates a new client with the given data.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->post("api/v1/clients", [
'headers' => [
"Authorization" => "Bearer {token}",
"Content-Type" => "application/json",
],
'json' => [
"name" => "John Doe",
"email" => "john.doe@example.com",
"ean" => 5789012345678,
"phone" => 7380111233,
"zip" => "M14 5PT",
"city" => "Manchester",
"cpr" => "0123456789",
"notes" => "Some notes",
"tags" => [
[
"id" => 15,
],
[
"name" => "Gold clients",
],
],
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X POST "https://system.easypractice.net/api/v1/clients" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"name":"John Doe","email":"john.doe@example.com","ean":5789012345678,"phone":7380111233,"zip":"M14 5PT","city":"Manchester","cpr":"0123456789","notes":"Some notes","tags":[{"id":15},{"name":"Gold clients"}]}'
const url = new URL("https://system.easypractice.net/api/v1/clients");
let headers = {
"Authorization": "Bearer {token}",
"Content-Type": "application/json",
"Accept": "application/json",
}
let body = {
"name": "John Doe",
"email": "john.doe@example.com",
"ean": 5789012345678,
"phone": 7380111233,
"zip": "M14 5PT",
"city": "Manchester",
"cpr": "0123456789",
"notes": "Some notes",
"tags": [
{
"id": 15
},
{
"name": "Gold clients"
}
]
}
fetch(url, {
method: "POST",
headers: headers,
body: body
})
.then(response => response.json())
.then(json => console.log(json));
Example response (201):
{
"message": "Created",
"data": {
"id": 123,
"name": "John Doe",
"email": "john.doe@example.com",
"ean": "5789012345678",
"phone": "7380111233",
"zip": "M14 5PT",
"city": "Manchester",
"cpr": "0123456789",
"notes": "Some notes"
}
}
Example response (422):
{
"error": {
"message": "The given data is invalid",
"status_code": 422
},
"data": {
"name": [
"The Name field is required."
]
}
}
HTTP Request
POST api/v1/clients
Body Parameters
Parameter | Type | Status | Description |
---|---|---|---|
name | string | required | The Name of the client. |
string | optional | The Email of the client. | |
ean | string | optional | The EAN-number of the client. |
phone | string | optional | The Phone of the client without the country code. |
zip | string | optional | The Zip/Postcode of the client. |
city | string | optional | The City of the client. |
cpr | string | optional | The CPR of the client. |
notes | string | optional | The Notes of the client. |
tags | array | optional | The tags associated to the client. It's possible to use the id or the name for each tag. |
Show client
Requires authentication
Returns the client data for a given ID.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->get("api/v1/clients/1", [
'headers' => [
"Authorization" => "Bearer {token}",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X GET -G "https://system.easypractice.net/api/v1/clients/1" \
-H "Authorization: Bearer {token}"
const url = new URL("https://system.easypractice.net/api/v1/clients/1");
let headers = {
"Authorization": "Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
fetch(url, {
method: "GET",
headers: headers,
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"id": 1,
"name": "John Smith",
"email": "john@mydomain.dk",
"phone": "61175736",
"address": "159 Bailey Brooks",
"zip": "W10 6DY",
"city": "Copenhagen",
"cpr": "1598431234",
"notes": "Notes about John",
"profile_image_url": "https:\/\/www.gravatar.com\/avatar\/5ea799d8476cbe0b1965c39e7c7dbd99?d=mm&s=200",
"created_at": "2019-04-16 11:54:42",
"tags": []
}
Example response (404):
{
"error": {
"message": "Not Found",
"status_code": 404
}
}
HTTP Request
GET api/v1/clients/{client}
Update client
Requires authentication
Updates the client.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->put("api/v1/clients/1", [
'headers' => [
"Authorization" => "Bearer {token}",
"Content-Type" => "application/json",
],
'json' => [
"name" => "John Doe",
"email" => "john.doe@example.com",
"ean" => 5789012345678,
"phone" => 7380111233,
"zip" => "M14 5PT",
"city" => "Manchester",
"cpr" => "0123456789",
"notes" => "Some notes",
"tags" => [
[
"id" => 15,
],
[
"name" => "Gold clients",
],
],
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X PUT "https://system.easypractice.net/api/v1/clients/1" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"name":"John Doe","email":"john.doe@example.com","ean":5789012345678,"phone":7380111233,"zip":"M14 5PT","city":"Manchester","cpr":"0123456789","notes":"Some notes","tags":[{"id":15},{"name":"Gold clients"}]}'
const url = new URL("https://system.easypractice.net/api/v1/clients/1");
let headers = {
"Authorization": "Bearer {token}",
"Content-Type": "application/json",
"Accept": "application/json",
}
let body = {
"name": "John Doe",
"email": "john.doe@example.com",
"ean": 5789012345678,
"phone": 7380111233,
"zip": "M14 5PT",
"city": "Manchester",
"cpr": "0123456789",
"notes": "Some notes",
"tags": [
{
"id": 15
},
{
"name": "Gold clients"
}
]
}
fetch(url, {
method: "PUT",
headers: headers,
body: body
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"message": "Updated",
"data": {
"id": 1,
"name": "John Doe",
"email": "john.doe@example.com",
"ean": "5789012345678",
"phone": "7380111233",
"zip": "M14 5PT",
"city": "Manchester",
"cpr": "0123456789",
"notes": "Some notes",
"tags": []
}
}
Example response (422):
{
"error": {
"message": "The given data is invalid",
"status_code": 422
},
"data": {
"name": [
"The Name field is required."
]
}
}
HTTP Request
PUT api/v1/clients/{client}
PATCH api/v1/clients/{client}
Body Parameters
Parameter | Type | Status | Description |
---|---|---|---|
name | string | required | The Name of the client. |
string | optional | The Email of the client. | |
ean | string | optional | The EAN-number of the client. |
phone | string | optional | The Phone of the client without the country code. |
zip | string | optional | The Zip/Postcode of the client. |
city | string | optional | The City of the client. |
cpr | string | optional | The CPR of the client. |
notes | string | optional | The Notes of the client. |
tags | array | optional | The tags associated to the client. It's possible to use the id or the name for each tag. |
Delete client
Requires authentication
Removes the client from the user's account and all of its associated data, such as bookings/journals/messages. Use with caution.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->delete("api/v1/clients/1", [
'headers' => [
"Authorization" => "Bearer {token}",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X DELETE "https://system.easypractice.net/api/v1/clients/1" \
-H "Authorization: Bearer {token}"
const url = new URL("https://system.easypractice.net/api/v1/clients/1");
let headers = {
"Authorization": "Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
fetch(url, {
method: "DELETE",
headers: headers,
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"message": "Deleted"
}
HTTP Request
DELETE api/v1/clients/{client}
Client tags
List clients tags.
Requires authentication
Returns all of user's clients tags. Use the filter options provided to order the results. For example: GET api/v1/clients?order_by_tag=asc
. Please note that this is an endpoint to administer the tags already created on the user. If you need to add/remove tags from clients, then use the Clients endpoint instead.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->get("api/v1/client-tags", [
'headers' => [
"Authorization" => "Bearer {token}",
],
'query' => [
"order_by_name" => "asc",
"page_size" => "20",
"page" => "4",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X GET -G "https://system.easypractice.net/api/v1/client-tags" \
-H "Authorization: Bearer {token}"
const url = new URL("https://system.easypractice.net/api/v1/client-tags");
let params = {
"order_by_name": "asc",
"page_size": "20",
"page": "4",
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
let headers = {
"Authorization": "Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
fetch(url, {
method: "GET",
headers: headers,
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"data": [
{
"id": 1,
"name": "Premium clients"
},
{
"id": 2,
"name": "Gold clients"
}
],
"links": {
"...": "..."
},
"meta": {
"...": "..."
}
}
HTTP Request
GET api/v1/client-tags
Query Parameters
Parameter | Status | Description |
---|---|---|
order_by_name | optional | =[asc|desc] Order results by name. |
page_size | optional | (default: 10) The number of items per page. |
page | optional | (default: 1) The page number. |
Create clients tag.
Requires authentication
Creates a new clients tag with the given data.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->post("api/v1/client-tags", [
'headers' => [
"Authorization" => "Bearer {token}",
"Content-Type" => "application/json",
],
'json' => [
"name" => "Premium clients",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X POST "https://system.easypractice.net/api/v1/client-tags" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"name":"Premium clients"}'
const url = new URL("https://system.easypractice.net/api/v1/client-tags");
let headers = {
"Authorization": "Bearer {token}",
"Content-Type": "application/json",
"Accept": "application/json",
}
let body = {
"name": "Premium clients"
}
fetch(url, {
method: "POST",
headers: headers,
body: body
})
.then(response => response.json())
.then(json => console.log(json));
Example response (201):
{
"message": "The new tag was created",
"data": {
"id": 123,
"name": "Premium clients"
}
}
Example response (422):
{
"error": {
"message": "The given data is invalid",
"status_code": 422
},
"data": {
"name": [
"The name field is required."
]
}
}
HTTP Request
POST api/v1/client-tags
Body Parameters
Parameter | Type | Status | Description |
---|---|---|---|
name | string | required | The Name of the tag. |
Show clients tag.
Requires authentication
Returns the clients tag data for a given ID.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->get("api/v1/client-tags/1", [
'headers' => [
"Authorization" => "Bearer {token}",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X GET -G "https://system.easypractice.net/api/v1/client-tags/1" \
-H "Authorization: Bearer {token}"
const url = new URL("https://system.easypractice.net/api/v1/client-tags/1");
let headers = {
"Authorization": "Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
fetch(url, {
method: "GET",
headers: headers,
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"id": 1,
"name": "Premium clients"
}
Example response (404):
{
"error": {
"message": "Not Found",
"status_code": 404
}
}
HTTP Request
GET api/v1/client-tags/{client_tag}
Update clients tag.
Requires authentication
Updates the clients tag.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->put("api/v1/client-tags/1", [
'headers' => [
"Authorization" => "Bearer {token}",
"Content-Type" => "application/json",
],
'json' => [
"name" => "Premium clients",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X PUT "https://system.easypractice.net/api/v1/client-tags/1" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"name":"Premium clients"}'
const url = new URL("https://system.easypractice.net/api/v1/client-tags/1");
let headers = {
"Authorization": "Bearer {token}",
"Content-Type": "application/json",
"Accept": "application/json",
}
let body = {
"name": "Premium clients"
}
fetch(url, {
method: "PUT",
headers: headers,
body: body
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"message": "The tag was updated",
"data": {
"id": 1,
"name": "Premium clients"
}
}
Example response (422):
{
"error": {
"message": "The given data is invalid",
"status_code": 422
},
"data": {
"name": [
"The name field is required."
]
}
}
HTTP Request
PUT api/v1/client-tags/{client_tag}
PATCH api/v1/client-tags/{client_tag}
Body Parameters
Parameter | Type | Status | Description |
---|---|---|---|
name | string | required | The Name of the tag. |
Delete clients tag.
Requires authentication
Removes the clients tag from the user's account.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->delete("api/v1/client-tags/1", [
'headers' => [
"Authorization" => "Bearer {token}",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X DELETE "https://system.easypractice.net/api/v1/client-tags/1" \
-H "Authorization: Bearer {token}"
const url = new URL("https://system.easypractice.net/api/v1/client-tags/1");
let headers = {
"Authorization": "Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
fetch(url, {
method: "DELETE",
headers: headers,
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"message": "Deleted"
}
HTTP Request
DELETE api/v1/client-tags/{client_tag}
Invoices
List invoices
Requires authentication
Returns all of user's invoices. Use the filter options provided to narrow down the results. For example: GET api/v1/invoices?client_id=123
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->get("api/v1/invoices", [
'headers' => [
"Authorization" => "Bearer {token}",
],
'query' => [
"client_id" => "54347",
"paid" => "1",
"unpaid" => "1",
"order_by_number" => "asc",
"page_size" => "20",
"page" => "4",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X GET -G "https://system.easypractice.net/api/v1/invoices" \
-H "Authorization: Bearer {token}"
const url = new URL("https://system.easypractice.net/api/v1/invoices");
let params = {
"client_id": "54347",
"paid": "1",
"unpaid": "1",
"order_by_number": "asc",
"page_size": "20",
"page": "4",
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
let headers = {
"Authorization": "Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
fetch(url, {
method: "GET",
headers: headers,
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"data": [
{
"id": 1,
"draft": false,
"client_id": 123,
"number": 454,
"date": "2019-04-20T00:00:00+01:00",
"due_date": "2019-04-20T00:00:00+01:00",
"executed_date": "2019-04-20T00:00:00+01:00",
"paid_date": "2019-04-20T00:00:00+01:00",
"sent": true,
"sent_via_ean": false,
"paid": true,
"credited": false,
"status": "paid",
"clientname": "John Doe",
"clientcpr": "123456-7890",
"clientaddress": "54 Harry Lane",
"clientzip": "1234",
"clientcity": "Copenhagen",
"payment_type": "card",
"currency": "DKK",
"total": 625,
"lines": [
{
"id": 23,
"invoice_id": 1,
"position": 0,
"amount": 1,
"price": 500,
"vat": true,
"vat_rate": 25,
"total_without_vat": 500,
"total": 625,
"text": "Client appointment",
"comment": "",
"booking_description": "Appointment Tuesday 16 April 2019, 16:05"
}
]
},
{
"id": 2,
"draft": false,
"client_id": 22,
"number": 455,
"date": "2019-05-01T00:00:00+01:00",
"due_date": "2019-05-01T00:00:00+01:00",
"executed_date": "2019-05-01T00:00:00+01:00",
"paid_date": "2019-05-01T00:00:00+01:00",
"sent": true,
"sent_via_ean": false,
"paid": true,
"credited": false,
"status": "paid",
"clientname": "Jaimes Armsworth",
"clientcpr": "121212-7890",
"clientaddress": "4 Snow Street",
"clientzip": "5454",
"clientcity": "Copenhagen",
"payment_type": "card",
"currency": "DKK",
"total": 1500,
"lines": [
{
"...": "..."
},
{
"...": "..."
}
]
}
],
"links": {
"...": "..."
},
"meta": {
"...": "..."
}
}
HTTP Request
GET api/v1/invoices
Query Parameters
Parameter | Status | Description |
---|---|---|
client_id | optional | Return only invoices belonging to this client ID. |
paid | optional | Return only the paid invoices. |
unpaid | optional | Return only the unpaid invoices. |
order_by_number | optional | =[asc|desc] Order results by invoice number. |
page_size | optional | (default: 10) The number of items per page. |
page | optional | (default: 1) The page number. |
Mark an invoice as paid
Requires authentication
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->post("api/v1/invoices/1/mark-as-paid", [
'headers' => [
"Authorization" => "Bearer {token}",
"Content-Type" => "application/json",
],
'json' => [
"date" => "2019-05-16",
"payment_type" => "card",
"amount" => 1500,
"currency" => "DKK",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X POST "https://system.easypractice.net/api/v1/invoices/1/mark-as-paid" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"date":"2019-05-16","payment_type":"card","amount":1500,"currency":"DKK"}'
const url = new URL("https://system.easypractice.net/api/v1/invoices/1/mark-as-paid");
let headers = {
"Authorization": "Bearer {token}",
"Content-Type": "application/json",
"Accept": "application/json",
}
let body = {
"date": "2019-05-16",
"payment_type": "card",
"amount": 1500,
"currency": "DKK"
}
fetch(url, {
method: "POST",
headers: headers,
body: body
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"message": "The Invoice 123 was marked as payed on 2019-05-20 with the payment method Card"
}
Example response (400):
{
"error": {
"message": "The Invoice 123 is already paid.",
"status_code": 400
}
}
Example response (422):
{
"error": {
"message": "The given data is invalid",
"status_code": 422
},
"data": {
"payment_type": [
"The selected Payment type is invalid."
]
}
}
HTTP Request
POST api/v1/invoices/{id}/mark-as-paid
Body Parameters
Parameter | Type | Status | Description |
---|---|---|---|
date | date | required | The Date of the payment. |
payment_type | string | required | The Payment method used. Available values: 'transfer', 'cash', 'card', 'other', 'mobile_pay' (Denmark only), 'health_insurance', 'swish' (Sweden only) |
amount | float | required | The Amount of the payment. |
currency | string | required | The Currency of the payment. |
Services
List services
Requires authentication
Returns all of user's services. Use the filter options provided to narrow down the results. For example: GET api/v1/services?order_by_name=asc
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->get("api/v1/services", [
'headers' => [
"Authorization" => "Bearer {token}",
],
'query' => [
"order_by_name" => "asc",
"page_size" => "20",
"page" => "4",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X GET -G "https://system.easypractice.net/api/v1/services" \
-H "Authorization: Bearer {token}"
const url = new URL("https://system.easypractice.net/api/v1/services");
let params = {
"order_by_name": "asc",
"page_size": "20",
"page": "4",
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
let headers = {
"Authorization": "Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
fetch(url, {
method: "GET",
headers: headers,
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"data": [
{
"id": 1,
"name": "Example of a service",
"description": "This is an example of your first service. You can either edit this service or delete it and create a new one to make if fit your practice",
"duration": 45,
"break_after_service": 15,
"currency": "DKK",
"price": 50,
"vat": true,
"vat_rate": 25,
"product_group_id": 0,
"is_available_in_online_booking": true,
"online_payment_enabled": true,
"reserve_online_payment": true,
"require_payment_in_advance": true,
"payment_rates_enabled": true,
"payment_rates_interval": "weekly",
"payment_rates_number": 4,
"calendars": [
{
"id": 12,
"name": "Calendar",
"color": "#C3E1FF"
}
],
"addons": [
{
"id": 2,
"name": "Additional time"
}
]
}
],
"links": {
"...": "..."
},
"meta": {
"...": "..."
}
}
HTTP Request
GET api/v1/services
Query Parameters
Parameter | Status | Description |
---|---|---|
order_by_name | optional | =[asc|desc] Order results by name. |
page_size | optional | (default: 10) The number of items per page. |
page | optional | (default: 1) The page number. |
Show service
Requires authentication
Returns the service data for a given ID.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->get("api/v1/services/1", [
'headers' => [
"Authorization" => "Bearer {token}",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X GET -G "https://system.easypractice.net/api/v1/services/1" \
-H "Authorization: Bearer {token}"
const url = new URL("https://system.easypractice.net/api/v1/services/1");
let headers = {
"Authorization": "Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
fetch(url, {
method: "GET",
headers: headers,
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"id": 1,
"name": "Example of a service",
"description": "This is an example of your first service. You can either edit this service or delete it and create a new one to make if fit your practice",
"duration": 45,
"break_after_service": 15,
"currency": "DKK",
"price": 50,
"vat": true,
"vat_rate": 25,
"product_group_id": 0,
"is_available_in_online_booking": true,
"online_payment_enabled": true,
"reserve_online_payment": true,
"require_payment_in_advance": true,
"payment_rates_enabled": true,
"payment_rates_interval": "weekly",
"payment_rates_number": 4,
"calendars": [
{
"id": 12,
"name": "Calendar",
"color": "#C3E1FF"
}
],
"addons": [
{
"id": 2,
"name": "Additional time"
}
]
}
Example response (404):
{
"error": {
"message": "Not Found",
"status_code": 404
}
}
HTTP Request
GET api/v1/services/{product}
List addons
Requires authentication
Returns all of user's addons. Addons are similar to services, but have fewer properties and their functionality depends on the service it is attached to during the booking (Online Payment, Payment Rates, etc). Use the filter options provided to narrow down the results. For example: GET api/v1/addons?order_by_name=asc
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->get("api/v1/addons", [
'headers' => [
"Authorization" => "Bearer {token}",
],
'query' => [
"order_by_name" => "asc",
"page_size" => "20",
"page" => "4",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X GET -G "https://system.easypractice.net/api/v1/addons" \
-H "Authorization: Bearer {token}"
const url = new URL("https://system.easypractice.net/api/v1/addons");
let params = {
"order_by_name": "asc",
"page_size": "20",
"page": "4",
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
let headers = {
"Authorization": "Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
fetch(url, {
method: "GET",
headers: headers,
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"data": [
{
"id": 2,
"name": "Additional time",
"description": "",
"duration": 15,
"break_after_service": 0,
"currency": "DKK",
"price": 15,
"vat": true,
"vat_rate": 25,
"is_available_in_online_booking": true,
"services": [
{
"id": 1,
"name": "Example of a service"
}
]
}
],
"links": {
"...": "..."
},
"meta": {
"...": "..."
}
}
HTTP Request
GET api/v1/addons
Query Parameters
Parameter | Status | Description |
---|---|---|
order_by_name | optional | =[asc|desc] Order results by name. |
page_size | optional | (default: 10) The number of items per page. |
page | optional | (default: 1) The page number. |
Show addon
Requires authentication
Returns the addon data for a given ID.
Example request:
$client = new \GuzzleHttp\Client();
$response = $client->get("api/v1/addons/1", [
'headers' => [
"Authorization" => "Bearer {token}",
],
]);
$body = $response->getBody();
print_r(json_decode((string) $body));
curl -X GET -G "https://system.easypractice.net/api/v1/addons/1" \
-H "Authorization: Bearer {token}"
const url = new URL("https://system.easypractice.net/api/v1/addons/1");
let headers = {
"Authorization": "Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
fetch(url, {
method: "GET",
headers: headers,
})
.then(response => response.json())
.then(json => console.log(json));
Example response (200):
{
"id": 2,
"name": "Additional time",
"description": "",
"duration": 15,
"break_after_service": 0,
"currency": "DKK",
"price": 15,
"vat": true,
"vat_rate": 25,
"is_available_in_online_booking": true,
"services": [
{
"id": 1,
"name": "Example of a service"
}
]
}
Example response (404):
{
"error": {
"message": "Not Found",
"status_code": 404
}
}
HTTP Request
GET api/v1/addons/{addon}