Introduction
This documentation aims to provide all the information you need to work with our API.
Authenticating requests
To authenticate requests, include an Authorization header with the value "Bearer {ACCESS_TOKEN}".
All authenticated endpoints are marked with a requires authentication badge in the documentation below.
Token based authentication
You can retrieve your access token by calling api/login endpoint.
Access tokens are valid 7 days, then expire. You can obtain new access token with expiring access token by calling /api/token/refresh. You can only refresh still valid tokens, otherwise new request to api/login will be required.
Cookie based authentication
You can also authenticate using cookie-based sessions. Before calling any other endpoints you have to obtain XSRF cookie by hitting /sanctum/csrf-cookie endpoint.
In return you receive XSRF-TOKEN cookie, which content you have to attach to each request as X-XSRF-TOKEN header.
Then call /login endpoint. When your authenticated session is created, call any endpoint using X-XSRF-TOKEN header.
Multi-Factor Authorization (MFA)
User can protect its account setting up the MFA as email or one-time passwords (OTP).
If mfa_enabled is set to 1 and mfa_method is set to any of email or otp values,
user will have to use preferred method as second factor on login.
If mfa_method is email, API will automatically send MFA code to user's email inbox.
Most of API endpoints are secured with additional layer and cannot be properly called without this second-factor authorization done.
Instead of endpoint response API will reply with message "MFA is required for this request." and HTTP code 401 Unauthorized.
That means user did not successfully authorized itself with second-factor.
Multi-Factor Authorization (MFA) - Remember Session
The user has the option to remember their device, which means they won't have to enter the MFA code for 30 days.
If using a Token based authentication, you need to add a header named X-MFA-Session-Token with the value {mfa_token} obtained from the /verify endpoint.
Appendix A. Laravel validation rules
List of validation codes returned for Laravel's built-in validation rules:
1, true, "yes" or "on".other field equals to value. Accepted values are the same as in MUST_BE_ACCEPTED.dns_get_record PHP function.date.date.date.date.min and max.min and max KB.min and max.min and max elements.true, false, 1, 0, "1" and "0".{field}_confirmation.strtotime PHP function.date.other.digits digits.min and max digits.value.value.value KB.value.value elements.value.value KB.value.value elements.values list.other field values.value.value KB.value.value elements.value.value KB.value.value elements.value.value KB.value.value elements.Note that the rule uses file extensions, but Laravel internally verifies the actual MIME type using the file's contents.
value.value KB.value.value elements.value.values list. This is the opposite of MUST_BE_IN rule.Field is considered empty if its value is null, an empty string, an empty array or a file input with no file uploaded.
other field is equal to value.other field is equal to value.values are present and not empty.values are present and not empty.values are not present or empty.values are not present or empty.other field is equal to value.other field is equal to value.other field can't be present at the same time.other field.size.size KB.size.size elements.value.timezone_identifiers_list PHP function.More detailed information about validation rules can be found in Laravel documentation.
Appendix B. Custom validation rules
List of custom validation rules messages:
maxmax.max_sizemax_size KB./api/timezones endpoint.content_typeRULES:URL_EXISTS_RULE:NOT_FOUND
If
content_type was specified, the rule also verifies the returned Content-Type header. If it doesn't match, the error code will include EXPECTED_CONTENT_TYPE:content_type.Otherwise, it only checks the status code and returns
NOT_FOUND if it's not 200.Fails if HTTP code is not 200 or the Content-Type doesn't match the expected value (if specified).
Acadle
Endpoints related to Acadle integration
Acadle SSO
requires authentication
Creates the SSO authorization link. The link expires after 60 seconds, but can be re-generated without any limits.
Example request:
curl --request POST \
"http://localhost:8000/api/acadle/sso" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/acadle/sso"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200, OK):
{
"sso_url": "https://adp.acadle.com/sso/authenticate/callback?ssoToken=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE3MzczNzU3OTksImV4cCI6MTczNzM3NTg1OSwiZmlyc3RuYW1lIjoiVG9tIiwibGFzdG5hbWUiOiJTbWl0aCIsImVtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsInVzZXJuYW1lIjpudWxsLCJ0aW1lem9uZSI6IlVUQyJ9.VzE2q6V53bdYJM7aB6CWWxDqcxF4gpdiEF80dD9j-5k",
"sso_expires": 1737375859
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to use Acadle",
"code": "ACADLE:SSO:INSUFFICIENT_PERMISSION"
}
Example response (403, Survey required):
{
"message": "Completing the survey is required to proceed to Acadle",
"code": "ACADLE:SSO:SURVEY_REQUIRED"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Check Acadle survey status
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/acadle/survey/status" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/acadle/survey/status"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"survey_sent": false,
"survey_id": null
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to use Acadle",
"code": "ACADLE:SURVEY_STATUS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Acadle survey data
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/acadle/survey" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/acadle/survey"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (201):
{
"id": 1,
"user_id": 296,
"cpo_number": "45",
"country": "Lebanon",
"medical_training": "clinician",
"myo_exp_zeus": "1",
"has_demo_hand_access": 0,
"wants_demo_hand": 1,
"myo_exp_covvi": 0,
"myo_exp_fillauer": 0,
"myo_exp_ossur": 0,
"myo_exp_ottobock": 0,
"myo_exp_steeper": 1,
"myo_exp_taska": 1,
"myo_exp_vincent": 1,
"myo_exp_pattern_recognition": 0,
"myo_exp_other": "Non sed quaerat atque eos et sapiente.",
"partial_hand_protheses": "3",
"below_elbow_protheses_single_action": "2",
"below_elbow_protheses_multi_action": "1",
"above_elbow_protheses": "4",
"shoulder_protheses": "5",
"zeus_components_description": "Perspiciatis aut animi aperiam nihil.",
"contact_name": "Alanna",
"contact_surname": "Reichel",
"company_name": "Murazik-Dicki",
"street": "411 Nitzsche Walk Suite 357",
"city": "New Kareemside",
"postal_code": "49509",
"email": "omayer@rodriguez.org",
"phone": "907.505.3585",
"phone_country": "ky",
"device_side": "L",
"created_at": "2026-02-27T12:42:49.000000Z",
"updated_at": "2026-02-27T12:42:49.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to use Acadle",
"code": "ACADLE:SURVEY_RESULTS:INSUFFICIENT_PERMISSION"
}
Example response (404, Survey not found):
{
"message": "Survey not found",
"code": "ACADLE:SURVEY_RESULTS:SURVEY_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Acadle survey data (SuperAdmin)
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/acadle/survey/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/acadle/survey/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (201):
{
"id": 2,
"user_id": 297,
"cpo_number": "2",
"country": "Argentina",
"medical_training": "physiotherapist",
"myo_exp_zeus": "0",
"has_demo_hand_access": 1,
"wants_demo_hand": 0,
"myo_exp_covvi": 1,
"myo_exp_fillauer": 1,
"myo_exp_ossur": 0,
"myo_exp_ottobock": 1,
"myo_exp_steeper": 0,
"myo_exp_taska": 1,
"myo_exp_vincent": 0,
"myo_exp_pattern_recognition": 0,
"myo_exp_other": "Corrupti autem omnis tempora reprehenderit cupiditate.",
"partial_hand_protheses": "0",
"below_elbow_protheses_single_action": "0",
"below_elbow_protheses_multi_action": "1",
"above_elbow_protheses": "1",
"shoulder_protheses": "0",
"zeus_components_description": "Excepturi optio maiores eligendi soluta et quis inventore.",
"contact_name": "Davion",
"contact_surname": "Keebler",
"company_name": "Kovacek-Schumm",
"street": "44671 Labadie Causeway",
"city": "West Freda",
"postal_code": "40410",
"email": "awunsch@schuppe.info",
"phone": "801.720.1094",
"phone_country": "km",
"device_side": "R",
"created_at": "2026-02-27T12:42:50.000000Z",
"updated_at": "2026-02-27T12:42:50.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to use Acadle",
"code": "ACADLE:SURVEY_RESULTS_ADMIN:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "ACADLE:SURVEY_RESULTS_ADMIN:USER_NOT_FOUND"
}
Example response (404, Survey not found):
{
"message": "Survey not found",
"code": "ACADLE:SURVEY_RESULTS_ADMIN:SURVEY_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List all Acadle surveys (SuperAdmin)
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/acadle/surveys?search=john" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/acadle/surveys"
);
const params = {
"search": "john",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 3,
"user_id": 298,
"cpo_number": "51",
"country": "Guadeloupe",
"medical_training": "biomedical_engineer",
"myo_exp_zeus": "1",
"has_demo_hand_access": 1,
"wants_demo_hand": 0,
"myo_exp_covvi": 0,
"myo_exp_fillauer": 1,
"myo_exp_ossur": 1,
"myo_exp_ottobock": 1,
"myo_exp_steeper": 0,
"myo_exp_taska": 0,
"myo_exp_vincent": 1,
"myo_exp_pattern_recognition": 0,
"myo_exp_other": "Sed illo adipisci et voluptatem et sint.",
"partial_hand_protheses": "2",
"below_elbow_protheses_single_action": "4",
"below_elbow_protheses_multi_action": "0",
"above_elbow_protheses": "2",
"shoulder_protheses": "5",
"zeus_components_description": "Iste neque minus optio aut consequatur iusto molestiae.",
"contact_name": "Norval",
"contact_surname": "DuBuque",
"company_name": "Kuvalis Inc",
"street": "56338 Kira Estates Apt. 131",
"city": "South Mauricio",
"postal_code": "84823",
"email": "yshields@kozey.biz",
"phone": "+1 (667) 625-4798",
"phone_country": "pg",
"device_side": "L",
"created_at": "2026-02-27T12:42:50.000000Z",
"updated_at": "2026-02-27T12:42:50.000000Z"
},
{
"id": 4,
"user_id": 299,
"cpo_number": "1334",
"country": "Norfolk Island",
"medical_training": "physiotherapist",
"myo_exp_zeus": "1",
"has_demo_hand_access": 0,
"wants_demo_hand": 0,
"myo_exp_covvi": 1,
"myo_exp_fillauer": 0,
"myo_exp_ossur": 0,
"myo_exp_ottobock": 0,
"myo_exp_steeper": 1,
"myo_exp_taska": 1,
"myo_exp_vincent": 1,
"myo_exp_pattern_recognition": 1,
"myo_exp_other": "Rerum aperiam iure nulla at magni deserunt est.",
"partial_hand_protheses": "4",
"below_elbow_protheses_single_action": "1",
"below_elbow_protheses_multi_action": "4",
"above_elbow_protheses": "3",
"shoulder_protheses": "2",
"zeus_components_description": "Est sint sapiente distinctio in.",
"contact_name": "Winifred",
"contact_surname": "O'Conner",
"company_name": "Streich and Sons",
"street": "768 Larkin Cove",
"city": "North Rudolph",
"postal_code": "99815-8493",
"email": "bergnaum.colleen@morar.com",
"phone": "458-709-2083",
"phone_country": "id",
"device_side": "R",
"created_at": "2026-02-27T12:42:50.000000Z",
"updated_at": "2026-02-27T12:42:50.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to use Acadle",
"code": "ACADLE:SURVEYS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Send Acadle survey
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/acadle/survey" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"cpo_number\": 6,
\"country\": \"Tokelau\",
\"medical_training\": \"physiotherapist\",
\"myo_exp_zeus\": false,
\"myo_exp_covvi\": false,
\"myo_exp_fillauer\": false,
\"myo_exp_ossur\": false,
\"myo_exp_ottobock\": false,
\"myo_exp_steeper\": false,
\"myo_exp_taska\": false,
\"myo_exp_vincent\": false,
\"myo_exp_pattern_recognition\": false,
\"myo_exp_other\": \"Est voluptatibus blanditiis ducimus ducimus maxime neque neque ab.\",
\"has_demo_hand_access\": false,
\"wants_demo_hand\": false,
\"partial_hand_protheses\": \"1-5\",
\"below_elbow_protheses_single_action\": \"1-5\",
\"below_elbow_protheses_multi_action\": \"5-10\",
\"above_elbow_protheses\": \"50+\",
\"shoulder_protheses\": \"1-5\",
\"zeus_components_description\": \"Libero molestias fugit quis doloremque.\",
\"contact_name\": \"Pablo\",
\"company_name\": \"Ebert, Bergstrom and Abbott\",
\"street\": \"652 Schinner Alley\",
\"city\": \"West Alannaland\",
\"postal_code\": \"15897-7438\",
\"email\": \"pacocha.katelyn@jenkins.info\",
\"phone\": \"+1 (269) 800-8996\",
\"phone_country\": \"VI\",
\"device_side\": \"R\"
}"
const url = new URL(
"http://localhost:8000/api/acadle/survey"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"cpo_number": 6,
"country": "Tokelau",
"medical_training": "physiotherapist",
"myo_exp_zeus": false,
"myo_exp_covvi": false,
"myo_exp_fillauer": false,
"myo_exp_ossur": false,
"myo_exp_ottobock": false,
"myo_exp_steeper": false,
"myo_exp_taska": false,
"myo_exp_vincent": false,
"myo_exp_pattern_recognition": false,
"myo_exp_other": "Est voluptatibus blanditiis ducimus ducimus maxime neque neque ab.",
"has_demo_hand_access": false,
"wants_demo_hand": false,
"partial_hand_protheses": "1-5",
"below_elbow_protheses_single_action": "1-5",
"below_elbow_protheses_multi_action": "5-10",
"above_elbow_protheses": "50+",
"shoulder_protheses": "1-5",
"zeus_components_description": "Libero molestias fugit quis doloremque.",
"contact_name": "Pablo",
"company_name": "Ebert, Bergstrom and Abbott",
"street": "652 Schinner Alley",
"city": "West Alannaland",
"postal_code": "15897-7438",
"email": "pacocha.katelyn@jenkins.info",
"phone": "+1 (269) 800-8996",
"phone_country": "VI",
"device_side": "R"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 5,
"user_id": 300,
"cpo_number": "908276802",
"country": "Cape Verde",
"medical_training": "clinician",
"myo_exp_zeus": "1",
"has_demo_hand_access": 0,
"wants_demo_hand": 0,
"myo_exp_covvi": 1,
"myo_exp_fillauer": 0,
"myo_exp_ossur": 1,
"myo_exp_ottobock": 0,
"myo_exp_steeper": 0,
"myo_exp_taska": 0,
"myo_exp_vincent": 1,
"myo_exp_pattern_recognition": 0,
"myo_exp_other": "Incidunt in non quo sit labore facere.",
"partial_hand_protheses": "3",
"below_elbow_protheses_single_action": "0",
"below_elbow_protheses_multi_action": "3",
"above_elbow_protheses": "0",
"shoulder_protheses": "5",
"zeus_components_description": "Id qui est enim.",
"contact_name": "Albertha",
"contact_surname": "Jacobs",
"company_name": "Daugherty and Sons",
"street": "16842 Michelle Lake Suite 025",
"city": "Lake Arvillabury",
"postal_code": "38085",
"email": "anna.pagac@mohr.com",
"phone": "443-618-2788",
"phone_country": "gw",
"device_side": "R",
"created_at": "2026-02-27T12:42:50.000000Z",
"updated_at": "2026-02-27T12:42:50.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to use Acadle",
"code": "ACADLE:SURVEY_SEND:INSUFFICIENT_PERMISSION"
}
Example response (403, Survey already sent):
{
"message": "Survey already sent",
"code": "ACADLE:SURVEY_SEND:SURVEY_ALREADY_SENT"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Activation codes
API endpoints for activation codes
Get activation codes
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/activation-codes" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/activation-codes"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"code": "ZT78ZO",
"created_by": 37,
"used_by": 38,
"used_at": null,
"active": 0,
"created_at": "2026-02-27T12:42:26.000000Z",
"updated_at": "2026-02-27T12:42:26.000000Z"
},
{
"id": 2,
"code": "3M8WQB",
"created_by": 39,
"used_by": 40,
"used_at": null,
"active": 1,
"created_at": "2026-02-27T12:42:26.000000Z",
"updated_at": "2026-02-27T12:42:26.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage activation codes",
"code": "ACTIVATION_CODE:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get active activation codes
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/activation-codes/active" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/activation-codes/active"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 3,
"code": "KNS0V2",
"created_by": 41,
"used_by": 42,
"used_at": null,
"active": 1,
"created_at": "2026-02-27T12:42:26.000000Z",
"updated_at": "2026-02-27T12:42:26.000000Z"
},
{
"id": 4,
"code": "I6ONAE",
"created_by": 43,
"used_by": 44,
"used_at": null,
"active": 0,
"created_at": "2026-02-27T12:42:26.000000Z",
"updated_at": "2026-02-27T12:42:26.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage activation codes",
"code": "ACTIVATION_CODE:ACTIVE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Find activation code
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/activation-codes/find/omnis" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/activation-codes/find/omnis"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 5,
"code": "8CV8DC",
"created_by": null,
"used_by": null,
"used_at": null,
"active": 0,
"created_at": "2026-02-27T12:42:26.000000Z",
"updated_at": "2026-02-27T12:42:26.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage activation codes",
"code": "ACTIVATION_CODE:FIND:INSUFFICIENT_PERMISSION"
}
Example response (404, Activation code not found):
{
"message": "Activation code not found",
"code": "ACTIVATION_CODE:FIND:CODE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create activation code
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/activation-codes" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/activation-codes"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (201):
{
"id": 6,
"code": "7TAJP7",
"created_by": null,
"used_by": null,
"used_at": null,
"active": 1,
"created_at": "2026-02-27T12:42:26.000000Z",
"updated_at": "2026-02-27T12:42:26.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage activation codes",
"code": "ACTIVATION_CODE:CREATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Server error):
{
"message": "Server error: activation code not created",
"code": "ACTIVATION_CODE:CREATE:SERVER_ERROR"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create activation code (multi-region)
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/activation-codes/6" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/activation-codes/6"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (201):
{
"id": 7,
"code": "3GTKR1",
"created_by": null,
"used_by": null,
"used_at": null,
"active": 1,
"created_at": "2026-02-27T12:42:26.000000Z",
"updated_at": "2026-02-27T12:42:26.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage activation codes",
"code": "ACTIVATION_CODE:CREATE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Deactivate activation code
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/activation-codes/3" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/activation-codes/3"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202):
{
"id": 8,
"code": "7FDC3U",
"created_by": null,
"used_by": null,
"used_at": null,
"active": 0,
"created_at": "2026-02-27T12:42:26.000000Z",
"updated_at": "2026-02-27T12:42:26.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage activation codes",
"code": "ACTIVATION_CODE:DEACTIVATE:INSUFFICIENT_PERMISSION"
}
Example response (403, Activation code is not active):
{
"message": "Cannot deactivate: code is not active",
"code": "ACTIVATION_CODE:DEACTIVATE:CODE_NOT_ACTIVE"
}
Example response (404, Activation code not found):
{
"message": "Activation code not found",
"code": "ACTIVATION_CODE:DEACTIVATE:CODE_NOT_FOUND"
}
Example response (500, Server error):
{
"message": "Server error: activation code not deactivated",
"code": "ACTIVATION_CODE:DEACTIVATE:SERVER_ERROR"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Authentication
API endpoints for managing authentication
Login user
Example request:
curl --request POST \
"http://localhost:8000/api/login" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"test@example.com\",
\"password\": \"secretpassword\"
}"
const url = new URL(
"http://localhost:8000/api/login"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "test@example.com",
"password": "secretpassword"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"access_token": "7|x7de9EgE0xiBNLgHU91DHvhj85HVgTG1bekCssIA",
"expires": "2021-10-25 17:05:25"
}
Example response (403, Too many attempts):
{
"message": "Login: too many attempts",
"code": "GENERAL:TOO_MANY_ATTEMPTS"
}
Example response (422, Invalid credentials):
{
"message": "The given data was invalid.",
"errors": {
"email": [
"Given credentials not found"
]
},
"code": "AUTH:LOGIN:INVALID_CREDENTIALS"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Register user
Example request:
curl --request POST \
"http://localhost:8000/api/register" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"region\": \"us\",
\"name\": \"Tom Smith\",
\"email\": \"name@domain.com\",
\"password\": \"Test123!\",
\"phone\": \"364-820-5372\",
\"phone_country\": \"US\",
\"language\": \"en\",
\"clinic_name\": \"Runolfsson, Von and Kuhlman\",
\"clinic_location\": \"South Edaburgh\",
\"address1\": \"3075 Morar Lodge\",
\"address2\": \"East Elenorstad, MI 35429-9106\",
\"mfa_enabled\": true,
\"mfa_method\": \"email\",
\"activation_code\": \"1A2B3C\"
}"
const url = new URL(
"http://localhost:8000/api/register"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"region": "us",
"name": "Tom Smith",
"email": "name@domain.com",
"password": "Test123!",
"phone": "364-820-5372",
"phone_country": "US",
"language": "en",
"clinic_name": "Runolfsson, Von and Kuhlman",
"clinic_location": "South Edaburgh",
"address1": "3075 Morar Lodge",
"address2": "East Elenorstad, MI 35429-9106",
"mfa_enabled": true,
"mfa_method": "email",
"activation_code": "1A2B3C"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 2,
"mrn": "S0B8GKYY1772196141",
"name": "Theresia Rutherford",
"email": "1772196141ulynch@example.org",
"language": "en",
"phone": "970.465.7791",
"phone_country": "FI",
"phone_verified_at": null,
"address1": "7285 Brando Rapid Apt. 424",
"address2": "East Ciaraside, PA 58927",
"postal_code": "70521",
"city": "Bogisich-Olson",
"country": "FR",
"clinic_name": "Toychester",
"clinic_location": "504 Muller Mountain Suite 910\nAltenwerthmouth, ME 09563-4542",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:21.000000Z",
"updated_at": "2026-02-27T12:42:21.000000Z",
"invitation_status": "accepted",
"acadle_invitation_status": null,
"roles": [
{
"id": 2,
"name": "ClinicAdmin"
}
]
}
Example response (403, Too many attempts):
{
"message": "Register: too many attempts",
"code": "GENERAL:TOO_MANY_ATTEMPTS"
}
Example response (403, E-mail in use (in another region)):
{
"message": "E-mail address already in use (in another region)",
"code": "AUTH:REGISTER:EMAIL_IN_USE"
}
Example response (403, Activation code is incorrect):
{
"message": "Activation code is incorrect",
"code": "AUTH:REGISTER:INCORRECT_CODE"
}
Example response (500, Server error):
{
"message": "Server error: user not created",
"code": "AUTH:REGISTER:SERVER_ERROR"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Register mobile user
Example request:
curl --request POST \
"http://localhost:8000/api/mobile/register" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"region\": \"us\",
\"name\": \"Tom Smith\",
\"email\": \"name@domain.com\",
\"password\": \"Test123!\",
\"language\": \"en\",
\"terms_accepted\": true
}"
const url = new URL(
"http://localhost:8000/api/mobile/register"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"region": "us",
"name": "Tom Smith",
"email": "name@domain.com",
"password": "Test123!",
"language": "en",
"terms_accepted": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 3,
"mrn": "PYOXEJ3D1772196141",
"name": "Dr. Gregorio Fahey V",
"email": "1772196141wpfeffer@example.com",
"language": "en",
"phone": "+1 (845) 855-1092",
"phone_country": "BB",
"phone_verified_at": null,
"address1": "1090 Grady Light Suite 873",
"address2": "East Halietown, AR 50329",
"postal_code": "08894-0376",
"city": "Schamberger, Mayer and Wiza",
"country": "DK",
"clinic_name": "Theresiaton",
"clinic_location": "346 Hettinger Gardens Apt. 614\nSouth Larue, WI 24682",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:21.000000Z",
"updated_at": "2026-02-27T12:42:21.000000Z",
"invitation_status": "accepted",
"acadle_invitation_status": null,
"roles": [
{
"id": 2,
"name": "ClinicAdmin"
}
]
}
Example response (403, Too many attempts):
{
"message": "Register: too many attempts",
"code": "GENERAL:TOO_MANY_ATTEMPTS"
}
Example response (403, E-mail in use (in another region)):
{
"message": "E-mail address already in use (in another region)",
"code": "AUTH:MOBILE_REGISTER:EMAIL_IN_USE"
}
Example response (500, Server error):
{
"message": "Server error: user not created",
"code": "AUTH:MOBILE_REGISTER:SERVER_ERROR"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Request password reset
Request sending password reset email message with token that allows to change the password
Example request:
curl --request POST \
"http://localhost:8000/api/password/reset" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"test@example.com\"
}"
const url = new URL(
"http://localhost:8000/api/password/reset"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "test@example.com"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"code": "passwords.sent",
"message": "Reset password link successfully sent"
}
Example response (400, Throttled request):
{
"code": "passwords.throttled",
"message": "You have requested password reset recently"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Verify password reset token
Check if token is valid before using it to reset password
Example request:
curl --request POST \
"http://localhost:8000/api/password/reset/verify" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"token\": \"158bed12188492617e43ecfcca43f5990b3f5f0383b5083247389482b70af019\",
\"email\": \"test@example.com\"
}"
const url = new URL(
"http://localhost:8000/api/password/reset/verify"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"token": "158bed12188492617e43ecfcca43f5990b3f5f0383b5083247389482b70af019",
"email": "test@example.com"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"message": "Valid token",
"code": "AUTH:PASSWORD_RESET_VERIFY:VALID_TOKEN"
}
Example response (400, Invalid token):
{
"message": "Invalid token",
"code": "AUTH:PASSWORD_RESET_VERIFY:INVALID_TOKEN"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "AUTH:PASSWORD_RESET_VERIFY:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Change password with token
Change user password using password reset token sent to email address
Example request:
curl --request POST \
"http://localhost:8000/api/password/reset/change" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"token\": \"158bed12188492617e43ecfcca43f5990b3f5f0383b5083247389482b70af019\",
\"email\": \"test@example.com\",
\"password\": \"secretpassword\"
}"
const url = new URL(
"http://localhost:8000/api/password/reset/change"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"token": "158bed12188492617e43ecfcca43f5990b3f5f0383b5083247389482b70af019",
"email": "test@example.com",
"password": "secretpassword"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"code": "passwords.reset",
"message": "Password changed successfully"
}
Example response (400, Invalid token):
{
"code": "passwords.token",
"message": "Invalid token"
}
Example response (404, User not found):
{
"code": "passwords.user",
"message": "User not found"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Logout current device
requires authentication
Logout and delete current access token
Example request:
curl --request POST \
"http://localhost:8000/api/logout" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/logout"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (202):
[]
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Logout everywhere
requires authentication
Logout and delete all access tokens owned by account
Example request:
curl --request POST \
"http://localhost:8000/api/logout/everywhere" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/logout/everywhere"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (202):
[]
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Refresh access token
requires authentication
Refresh the new access token from the expiring token
Example request:
curl --request POST \
"http://localhost:8000/api/token/refresh" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/token/refresh"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200, OK):
{
"access_token": "7|x7de9EgE0xiBNLgHU91DHvhj85HVgTG1bekCssIA",
"expires": "2021-10-25 17:05:25"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Check MFA status
requires authentication
Check any of available MFA methods. Supported methods: email, sms, otp.
Example request:
curl --request GET \
--get "http://localhost:8000/api/mfa/status" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/mfa/status"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"enabled": 1,
"method": "email",
"phone": 1,
"otp": 1
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
enabled
string
Determines if user enabled MFA
method
string
Preferred MFA method
phone
string
Determines if user has verified phone number and sms channel could be used
otp
string
Determines if user has setup OTP with authenticator application
Use recovery code
requires authentication
Use generated recovery code in order to access account in case when other MFA methods couldn't be used. This method only checks if code is valid, implement account access scenario on your own. Sent code is removed and couldn't be used anymore. If remaining_codes counter equals zero, generate a new set.
Example request:
curl --request POST \
"http://localhost:8000/api/mfa/recovery-code" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"code\": \"ZZASRM6S\"
}"
const url = new URL(
"http://localhost:8000/api/mfa/recovery-code"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"code": "ZZASRM6S"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"access_token": "7|x7de9EgE0xiBNLgHU91DHvhj85HVgTG1bekCssIA",
"expires": "2021-10-25 17:05:25",
"remaining_codes": 9
}
Example response (401, Invalid code):
{
"message": "Invalid code",
"code": "AUTH:USE_RECOVERY_CODE:INVALID_CODE"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Send MFA code
requires authentication
Send multi-factor authentication code via selected channel. Code is valid for 15 minutes.
Example request:
curl --request POST \
"http://localhost:8000/api/mfa/send" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"channel\": \"email\"
}"
const url = new URL(
"http://localhost:8000/api/mfa/send"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"channel": "email"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"message": "Code sent",
"code": "AUTH:SEND_MFA:SENT"
}
Example response (400, Channel SMS, phone number not verified):
{
"message": "Phone number is not verified",
"code": "AUTH:SEND_MFA:PHONE_NUMBER_NOT_VERIFIED"
}
Example response (500, Channel SMS, provider problem):
{
"message": "Code sending failed",
"code": "AUTH:SEND_MFA:SERVER_ERROR"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Verify MFA code
requires authentication
Verify multi-factor code obtained from selected channel.
Example request:
curl --request POST \
"http://localhost:8000/api/mfa/verify" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"channel\": \"email\",
\"remember_mfa_session\": true,
\"code\": \"445566\",
\"machine_key\": \"35282880-244a-4328-9435-2aaf432f3619\"
}"
const url = new URL(
"http://localhost:8000/api/mfa/verify"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"channel": "email",
"remember_mfa_session": true,
"code": "445566",
"machine_key": "35282880-244a-4328-9435-2aaf432f3619"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK, token auth):
{
"access_token": "7|x7de9EgE0xiBNLgHU91DHvhj85HVgTG1bekCssIA",
"expires": "2021-10-25 17:05:25",
"mfa_token": "fd63e55c-2a67-44b2-95b9-a771778e9971",
"mfa_expires": "2023-04-25 21:00:00"
}
Example response (200, OK, cookie auth):
{
"message": "OK",
"mfa_token": "fd63e55c-2a67-44b2-95b9-a771778e9971",
"mfa_expires": "2023-04-25 21:00:00"
}
Example response (401, Invalid code):
{
"message": "Invalid code",
"code": "AUTH:VERIFY_MFA:INVALID_CODE"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Verify phone number
requires authentication
Verify phone number with text message
Example request:
curl --request POST \
"http://localhost:8000/api/mfa/phone/verify" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"code\": \"445566\"
}"
const url = new URL(
"http://localhost:8000/api/mfa/phone/verify"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"code": "445566"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"message": "Phone number verified",
"code": "AUTH:VERIFY_PHONE:VERIFIED"
}
Example response (401, Invalid code):
{
"message": "Invalid code",
"code": "AUTH:VERIFY_PHONE:INVALID_CODE"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Verify MFA OTP
requires authentication
Verify one-time password (OTP). If verification is successful, new access token with additional permissions will be generated.
Example request:
curl --request POST \
"http://localhost:8000/api/mfa/otp/verify" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"code\": \"445566\"
}"
const url = new URL(
"http://localhost:8000/api/mfa/otp/verify"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"code": "445566"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK, token auth):
{
"access_token": "7|x7de9EgE0xiBNLgHU91DHvhj85HVgTG1bekCssIA",
"expires": "2021-10-25 17:05:25"
}
Example response (200, OK, cookie auth):
{
"message": "OK"
}
Example response (401, Invalid code):
{
"message": "Invalid code",
"code": "AUTH:VERIFY_MFA_OTP:INVALID_CODE"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Change password
requires authentication
Change authenticated user password
Example request:
curl --request POST \
"http://localhost:8000/api/password/change" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"old_password\": \"oldpassword\",
\"new_password\": \"newpassword\"
}"
const url = new URL(
"http://localhost:8000/api/password/change"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"old_password": "oldpassword",
"new_password": "newpassword"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"message": "Password changed successfully",
"code": "AUTH:PASSWORD_CHANGE:CHANGED"
}
Example response (422, Invalid old password):
{
"message": "The given data was invalid.",
"errors": {
"old_password": [
"Old password is incorrect"
]
},
"code": "AUTH:PASSWORD_CHANGE:INVALID_OLD_PASSWORD"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Set MFA status
requires authentication
Set MFA status and preferred method. Supported methods: email, sms, otp.
Example request:
curl --request POST \
"http://localhost:8000/api/mfa/status" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"enabled\": true,
\"method\": \"email\"
}"
const url = new URL(
"http://localhost:8000/api/mfa/status"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"enabled": true,
"method": "email"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"enabled": 1,
"method": "email",
"phone": 1,
"otp": 1
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Generate recovery codes
requires authentication
Generate recovery codes for authenticated user and revoke old ones. User could use these codes in case when couldn't use any of MFA methods (e.g. lost device with OTP app or device is not accessible right now).
Example request:
curl --request GET \
--get "http://localhost:8000/api/mfa/recovery-codes" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/mfa/recovery-codes"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"recovery_codes": [
"A3H8PF8P",
"IZ8CGK2H",
"DTYENLLT",
"0RKEZFST",
"9MPW91BS",
"S38Z6HS6",
"UF5ATOKP",
"HSZXP8EL",
"ZZASRM6S",
"07GR4CD1"
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Setup MFA OTP
requires authentication
Setup multi-factor authentication with one-time passwords (OTP). Use secret on your own or generate QR code with given url. Then user could scan QR code with authentication app (e.g. Microsoft Authenticator, Authy). If secret has been already generated, new secret will override existing one and revoke previous setup.
Example request:
curl --request POST \
"http://localhost:8000/api/mfa/otp/setup" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/mfa/otp/setup"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200, OK):
{
"secret": "VXGJ6JMIAWWDFXYDLKO3VG3RSGTS34BGMVTGQIEHMVVMJ2JBGCSNPQZDV4B6OMDIGI4UKCVCVKVMA7EASLHZEJWW4ZNKLAUTSZYN7EA",
"url": "otpauth://totp/AetherDigitalTherapy?issuer=AetherDigitalTherapy&secret=VXGJ6JMIAWWDFXYDLKO3VG3RSGTS34BGMVTGQIEHMVVMJ2JBGCSNPQZDV4B6OMDIGI4UKCVCVKVMA7EASLHZEJWW4ZNKLAUTSZYN7EA",
"recovery_codes": [
"A3H8PF8P",
"IZ8CGK2H",
"DTYENLLT",
"0RKEZFST",
"9MPW91BS",
"S38Z6HS6",
"UF5ATOKP",
"HSZXP8EL",
"ZZASRM6S",
"07GR4CD1"
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Login user (SPA)
Authorize user and create cookie-based session. Hit GET /sanctum/csrf-cookie endpoint to retrieve XSRF-TOKEN cookie. Then attach X-XSRF-TOKEN HTTP header to any request to authorize. See more: Laravel Sanctum documentation
Example request:
curl --request POST \
"http://localhost:8000/login" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"test@example.com\",
\"password\": \"secretpassword\"
}"
const url = new URL(
"http://localhost:8000/login"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "test@example.com",
"password": "secretpassword"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"id": 324,
"mrn": "OBJAIT121772196172",
"name": "Delta Moore",
"email": "1772196172heller.marjolaine@example.net",
"language": "en",
"phone": "1-334-941-4873",
"phone_country": "GH",
"phone_verified_at": null,
"address1": "49315 Pollich Freeway",
"address2": "Darefurt, OR 30817",
"postal_code": "52493",
"city": "Fay Group",
"country": "FR",
"clinic_name": "Magdalenafort",
"clinic_location": "6413 Ullrich Alley Suite 497\nNew Alexandrehaven, SD 97404",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:52.000000Z",
"updated_at": "2026-02-27T12:42:52.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
Example response (403, Too many attempts):
{
"message": "Login: too many attempts",
"code": "GENERAL:TOO_MANY_ATTEMPTS"
}
Example response (422, Invalid credentials):
{
"message": "The given data was invalid.",
"errors": {
"email": [
"Given credentials not found"
]
},
"code": "AUTH:LOGIN_COOKIE:INVALID_CREDENTIALS"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Chat
API endpoints for chat management
Authorize a user
requires authentication
This method authorizes a user using Ably service. Endpoint used only by Ably SDK
Check more details on https://ably.com/docs/auth/token
List all chat rooms
requires authentication
This method retrieves all chat rooms. Possible extend options:
- participants - user assigned to chat room
- participants.roles - roles assigned to chat participants
- owner - the clinician assigned to patient
- patient - the patient for whom the chat was created
- messages - the messages related to chat room
- messages.author - the author of message/li>
Example request:
curl --request GET \
--get "http://localhost:8000/api/chat/rooms" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/chat/rooms"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"owner": null,
"patient_id": null,
"encryption_key": "8c/HqSuVkSzebJCvYdXgDEcAKoEvDfi3/jb0y7QMDtc=",
"name": "animi",
"friendly_name": "animi",
"created_at": "2026-02-27T12:42:48.000000Z",
"deleted_at": null,
"updated_at": "2026-02-27T12:42:48.000000Z"
},
{
"id": 2,
"owner": null,
"patient_id": null,
"encryption_key": "tuNDrvuQmB8sqpY7O1y4ljvO6RKpszDfh7HK+kRU93U=",
"name": "dolor",
"friendly_name": "dolor",
"created_at": "2026-02-27T12:42:48.000000Z",
"deleted_at": null,
"updated_at": "2026-02-27T12:42:48.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list chat room",
"code": "CHAT:LIST_ROOMS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Retrieve a chat room
requires authentication
This method retrieves a single chat room identified by roomId. Possible extend options:
- participants - user assigned to chat room
- owner - the clinician assigned to patient
- patient - the patient for whom the chat was created
- messages - the messages related to chat room
- messages.author - the author of message/li>
Example request:
curl --request GET \
--get "http://localhost:8000/api/chat/room/modi" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/chat/room/modi"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 3,
"owner": null,
"patient_id": null,
"encryption_key": "yuZTFtH5VmC4tZQF/IJk1tNhpioow5Src/INbGkEX1U=",
"name": "velit",
"friendly_name": "velit",
"created_at": "2026-02-27T12:42:48.000000Z",
"deleted_at": null,
"updated_at": "2026-02-27T12:42:48.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view chat room",
"code": "CHAT:GET_ROOM:INSUFFICIENT_PERMISSION"
}
Example response (404, Chat room not found):
{
"message": "Chat room not found",
"code": "CHAT:GET_ROOM:ROOM_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create a new chat room
requires authentication
This method creates a new chat room using the authenticated user's ID, a name for the room, and a list of participants.
The list of participants should contain the IDs of the users who will be participants in the room.
Example request:
curl --request POST \
"http://localhost:8000/api/chat/room" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"owner\": 1,
\"name\": \"my-chat\",
\"patient_id\": 1,
\"participants\": [
\"1\"
]
}"
const url = new URL(
"http://localhost:8000/api/chat/room"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"owner": 1,
"name": "my-chat",
"patient_id": 1,
"participants": [
"1"
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 4,
"owner": null,
"patient_id": null,
"encryption_key": "AP8hzB6H1XMoH/YzFLu1mrxFBUxF/EEQOC8gMsIbKKk=",
"name": "fugiat",
"friendly_name": "fugiat",
"created_at": "2026-02-27T12:42:48.000000Z",
"deleted_at": null,
"updated_at": "2026-02-27T12:42:48.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view chat room",
"code": "CHAT:CREATE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update an existing chat room
requires authentication
This method updates an existing chat room using the authenticated user's ID, a new name for the room, and a list of participants.
The list of participants should contain the IDs of the users who will be participants in the room.
Example request:
curl --request PUT \
"http://localhost:8000/api/chat/room/facilis" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"owner\": 1,
\"name\": \"my-chat\",
\"participants\": [
\"1\"
],
\"participants_del\": [
\"1\"
]
}"
const url = new URL(
"http://localhost:8000/api/chat/room/facilis"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"owner": 1,
"name": "my-chat",
"participants": [
"1"
],
"participants_del": [
"1"
]
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 5,
"owner": null,
"patient_id": null,
"encryption_key": "1nWXa1BQsUO9PqDgskoJ2FC7jv12Ulebj8FwLuJTF/c=",
"name": "distinctio",
"friendly_name": "distinctio",
"created_at": "2026-02-27T12:42:49.000000Z",
"deleted_at": null,
"updated_at": "2026-02-27T12:42:49.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update chat room",
"code": "CHAT:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Chat room not found):
{
"message": "Chat room not found",
"code": "CHAT:UPDATE:ROOM_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Chat room archives
requires authentication
Get archived messages for room Possible extend options:
- author - this field represent user who send message
Example request:
curl --request GET \
--get "http://localhost:8000/api/chat/room/quam/archive" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/chat/room/quam/archive"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"paginator": {
"total": 1,
"count": 1,
"perpage": 5,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": "651a8e4868d5dc27c0000cc2",
"channel": "chat.messages.room.44.56bf7d37-4ed6-4db4-947b-d68a1066677c.communication-channel",
"clientId": "95",
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"data": "{\"encryptedMessage\":{\"message\":\"z6z1zNihCjlEePltz+BG8g==\",\"initialVector\":\"7376fcbf0b32fbdcd5c5b62c087b7600\"},\"user\":{\"id\":95,\"name\":\"Bartosz Druga firmaa\",\"email\":\"bartosz+drugafirma@refericon.pl\",\"image\":\"https://aether-dev-bucket.s3.amazonaws.com/users/7T6im01PAj4cahksWHllrL7se2SQ9buquIjGGFtp.jpg\",\"permissions\":[],\"roles\":[{\"id\":2,\"name\":\"Clinician\"}]},\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"recipients\":[{\"delivered\":true,\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"seen\":false,\"clientId\":\"95\"},{\"delivered\":true,\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"seen\":false,\"clientId\":\"44\"},{\"delivered\":true,\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"seen\":false,\"clientId\":\"1250\"},{\"delivered\":true,\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"seen\":false,\"clientId\":\"3067\"}]}",
"name": "message",
"recipients": [
{
"delivered": true,
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"seen": true,
"clientId": "95"
},
{
"delivered": true,
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"seen": false,
"clientId": "44"
},
{
"delivered": true,
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"seen": false,
"clientId": "1250"
},
{
"delivered": true,
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"seen": false,
"clientId": "3067"
}
],
"timestamp": 1696239176715,
"created_at": "2023-10-02 09:32:56"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view archived messages",
"code": "CHAT:GET_ARCHIVES:INSUFFICIENT_PERMISSION"
}
Example response (404, Chat room not found):
{
"message": "Chat room not found",
"code": "CHAT:GET_ARCHIVES:ROOM_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Unread messages
requires authentication
Get unread messaged for chat room. Possible extend options:
- author - this field represent user who send message
Example request:
curl --request GET \
--get "http://localhost:8000/api/chat/messages/unread?room=20" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/chat/messages/unread"
);
const params = {
"room": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"paginator": {
"total": 1,
"count": 1,
"perpage": 5,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": "651a8e4868d5dc27c0000cc2",
"channel": "chat.messages.room.44.56bf7d37-4ed6-4db4-947b-d68a1066677c.communication-channel",
"clientId": "95",
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"data": "{\"encryptedMessage\":{\"message\":\"z6z1zNihCjlEePltz+BG8g==\",\"initialVector\":\"7376fcbf0b32fbdcd5c5b62c087b7600\"},\"user\":{\"id\":95,\"name\":\"Bartosz Druga firmaa\",\"email\":\"bartosz+drugafirma@refericon.pl\",\"image\":\"https://aether-dev-bucket.s3.amazonaws.com/users/7T6im01PAj4cahksWHllrL7se2SQ9buquIjGGFtp.jpg\",\"permissions\":[],\"roles\":[{\"id\":2,\"name\":\"Clinician\"}]},\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"recipients\":[{\"delivered\":true,\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"seen\":false,\"clientId\":\"95\"},{\"delivered\":true,\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"seen\":false,\"clientId\":\"44\"},{\"delivered\":true,\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"seen\":false,\"clientId\":\"1250\"},{\"delivered\":true,\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"seen\":false,\"clientId\":\"3067\"}]}",
"name": "message",
"recipients": [
{
"delivered": true,
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"seen": true,
"clientId": "95"
},
{
"delivered": true,
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"seen": false,
"clientId": "44"
},
{
"delivered": true,
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"seen": false,
"clientId": "1250"
},
{
"delivered": true,
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"seen": false,
"clientId": "3067"
}
],
"timestamp": 1696239176715,
"created_at": "2023-10-02 09:32:56"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view unread messages list",
"code": "CHAT:UNREAD_MESSAGES:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete chat message
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/chat/messages/8?msgId=omnis" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/chat/messages/8"
);
const params = {
"msgId": "omnis",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"paginator": {
"total": 1,
"count": 1,
"perpage": 5,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": "651a8e4868d5dc27c0000cc2",
"channel": "chat.messages.room.44.56bf7d37-4ed6-4db4-947b-d68a1066677c.communication-channel",
"clientId": "95",
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"data": "{\"encryptedMessage\":{\"message\":\"z6z1zNihCjlEePltz+BG8g==\",\"initialVector\":\"7376fcbf0b32fbdcd5c5b62c087b7600\"},\"user\":{\"id\":95,\"name\":\"Bartosz Druga firmaa\",\"email\":\"bartosz+drugafirma@refericon.pl\",\"image\":\"https://aether-dev-bucket.s3.amazonaws.com/users/7T6im01PAj4cahksWHllrL7se2SQ9buquIjGGFtp.jpg\",\"permissions\":[],\"roles\":[{\"id\":2,\"name\":\"Clinician\"}]},\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"recipients\":[{\"delivered\":true,\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"seen\":false,\"clientId\":\"95\"},{\"delivered\":true,\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"seen\":false,\"clientId\":\"44\"},{\"delivered\":true,\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"seen\":false,\"clientId\":\"1250\"},{\"delivered\":true,\"msgId\":\"b8673175-01e6-4b6d-9032-226d3df20637\",\"seen\":false,\"clientId\":\"3067\"}]}",
"name": "message",
"recipients": [
{
"delivered": true,
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"seen": true,
"clientId": "95"
},
{
"delivered": true,
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"seen": false,
"clientId": "44"
},
{
"delivered": true,
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"seen": false,
"clientId": "1250"
},
{
"delivered": true,
"msgId": "b8673175-01e6-4b6d-9032-226d3df20637",
"seen": false,
"clientId": "3067"
}
],
"timestamp": 1696239176715,
"created_at": "2023-10-02 09:32:56"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to delete message",
"code": "CHAT:DELETE_MESSAGE:INSUFFICIENT_PERMISSION"
}
Example response (404, Message not found):
{
"message": "Chat message not found",
"code": "CHAT:DELETE_MESSAGE:MESSAGE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get tickets list for chat room
requires authentication
Possible extend options:
- sender - the user who created ticket
- recipient - the user who was ticket recipient
- messages - message allocated to ticket
- messages.attachments - list of attachments assigned to message and ticket
- messages.sender - the user who wrote the message
Example request:
curl --request GET \
--get "http://localhost:8000/api/chat/tickets/magni?status=atque&sender=5&recipient=5" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/chat/tickets/magni"
);
const params = {
"status": "atque",
"sender": "5",
"recipient": "5",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 87,
"sender_id": 288,
"recipient_id": 289,
"device_id": null,
"meeting_date": "2026-02-27 12:42:49",
"meeting_type": "online_meeting",
"contact_email": "ikuphal@yahoo.com",
"status": "new",
"created_at": "2026-02-27T12:42:49.000000Z",
"updated_at": "2026-02-27T12:42:49.000000Z",
"sender": {
"id": 288,
"mrn": "0H7PT2AM1772196169",
"name": "Dr. Zola Kris",
"email": "1772196169jefferey51@example.com",
"language": "en",
"phone": "+1-785-689-8763",
"phone_country": "CM",
"phone_verified_at": null,
"address1": "5194 Savannah Islands Suite 112",
"address2": "North Alfonso, HI 68437",
"postal_code": "47260-8296",
"city": "Hermann LLC",
"country": "LV",
"clinic_name": "West Stanley",
"clinic_location": "706 Kshlerin Loop\nWilfridborough, ME 40235",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:49.000000Z",
"updated_at": "2026-02-27T12:42:49.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"recipient": {
"id": 289,
"mrn": "RSNMVAJS1772196169",
"name": "Dr. Kiarra King",
"email": "1772196169mcdermott.shirley@example.net",
"language": "en",
"phone": "1-650-515-1830",
"phone_country": "BB",
"phone_verified_at": null,
"address1": "58878 Holden Forge Suite 201",
"address2": "Wintheiserbury, IN 27337-7181",
"postal_code": "82999",
"city": "Trantow-Bednar",
"country": "IN",
"clinic_name": "Emardtown",
"clinic_location": "14184 Spinka Brook\nPfeffermouth, WY 96522",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:49.000000Z",
"updated_at": "2026-02-27T12:42:49.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"device": null,
"messages": []
},
{
"id": 88,
"sender_id": 290,
"recipient_id": 291,
"device_id": null,
"meeting_date": "2026-02-27 12:42:49",
"meeting_type": "online_meeting",
"contact_email": "irwin.shields@zboncak.com",
"status": "new",
"created_at": "2026-02-27T12:42:49.000000Z",
"updated_at": "2026-02-27T12:42:49.000000Z",
"sender": {
"id": 290,
"mrn": "I3883HCC1772196169",
"name": "Prof. Jaylin Kertzmann DDS",
"email": "1772196169tyson32@example.net",
"language": "en",
"phone": "223-589-1866",
"phone_country": "GG",
"phone_verified_at": null,
"address1": "29732 Mustafa Inlet",
"address2": "Cruickshankview, NE 28828",
"postal_code": "79955",
"city": "Marvin, Mraz and Volkman",
"country": "HU",
"clinic_name": "Roweburgh",
"clinic_location": "131 Dach Ridge Suite 402\nAssuntafurt, OH 08393-8739",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:49.000000Z",
"updated_at": "2026-02-27T12:42:49.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"recipient": {
"id": 291,
"mrn": "EYIU1BV41772196169",
"name": "Colt Bernier",
"email": "1772196169qolson@example.org",
"language": "en",
"phone": "678-613-5666",
"phone_country": "UG",
"phone_verified_at": null,
"address1": "7609 Flatley Underpass",
"address2": "Hahnborough, AL 49144-4472",
"postal_code": "93621",
"city": "West, Padberg and Wolff",
"country": "CZ",
"clinic_name": "Wardfort",
"clinic_location": "82861 Dooley Overpass Apt. 377\nMaggioport, MI 45226",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:49.000000Z",
"updated_at": "2026-02-27T12:42:49.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"device": null,
"messages": []
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view chat room tickets",
"code": "CHAT:LIST_TICKETS:INSUFFICIENT_PERMISSION"
}
Example response (404, Chat room not found):
{
"message": "Chat room not found",
"code": "CHAT:LIST_TICKETS:ROOM_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List of available patients for chat
requires authentication
Possible extend options:
- clinician - clinician assigned to this user
- devices - products assigned to user
- roles - user roles
Example request:
curl --request GET \
--get "http://localhost:8000/api/chat/available-patients" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/chat/available-patients"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 292,
"mrn": "LSBKF8T81772196169",
"name": "Dr. Catalina Paucek",
"email": "1772196169keanu90@example.net",
"language": "en",
"phone": "+1 (803) 900-5254",
"phone_country": "HU",
"phone_verified_at": null,
"address1": "69642 Breana Shoals",
"address2": "Port Icie, CT 45428-3756",
"postal_code": "07616",
"city": "Hettinger-Johnston",
"country": "SK",
"clinic_name": "Collinsfurt",
"clinic_location": "4935 Moore Loaf\nEast Gabrielfort, IA 54278",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:49.000000Z",
"updated_at": "2026-02-27T12:42:49.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"devices": [
{
"id": 141,
"serial": "355c5ff9-ff94-3ead-8c3d-86852c5b1439",
"bluetooth_id": "6d070872-b9e8-3a84-ac9a-b42633295817",
"company_id": null,
"model_id": null,
"amputee_id": 292,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:49.000000Z",
"updated_at": "2026-02-27T12:42:49.000000Z"
}
],
"roles": [
{
"id": 5,
"name": "Amputee"
}
]
},
{
"id": 293,
"mrn": "BUT315O11772196169",
"name": "Alison Jacobi DDS",
"email": "1772196169claudie66@example.org",
"language": "en",
"phone": "1-740-285-8243",
"phone_country": "BE",
"phone_verified_at": null,
"address1": "944 Hegmann Estate Apt. 390",
"address2": "East Treyside, CA 69220-4374",
"postal_code": "25684",
"city": "Christiansen-Hodkiewicz",
"country": "MT",
"clinic_name": "Maudieville",
"clinic_location": "4535 Ferry Stravenue Suite 316\nMaximeburgh, OK 30934",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:49.000000Z",
"updated_at": "2026-02-27T12:42:49.000000Z",
"invitation_status": "accepted",
"acadle_invitation_status": null,
"devices": [
{
"id": 142,
"serial": "2e7f4e98-a6a4-3b8c-bfe1-94265cfaf7bd",
"bluetooth_id": "2b413d12-330c-3b67-b3f9-473a0b36b928",
"company_id": null,
"model_id": null,
"amputee_id": 293,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:49.000000Z",
"updated_at": "2026-02-27T12:42:49.000000Z"
}
],
"roles": [
{
"id": 3,
"name": "Clinician"
}
]
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list available patients",
"code": "CHAT:LIST_PATIENTS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List of available participants for chat
requires authentication
Possible extend options:
- roles - user roles
- permissions - user permissions
Example request:
curl --request GET \
--get "http://localhost:8000/api/chat/room/1/available-participants" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/chat/room/1/available-participants"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 294,
"mrn": "9WJRB6ZB1772196169",
"name": "Miss Karen DuBuque DVM",
"email": "1772196169cassin.dion@example.net",
"language": "en",
"phone": "423-293-2603",
"phone_country": "UZ",
"phone_verified_at": null,
"address1": "605 Murazik Brooks Suite 595",
"address2": "Dereckmouth, NY 67344",
"postal_code": "89830-4593",
"city": "Mosciski, Wolff and Legros",
"country": "NO",
"clinic_name": "Dibbertborough",
"clinic_location": "794 Frieda Flats Apt. 869\nEast Hortense, MI 25607-1902",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:49.000000Z",
"updated_at": "2026-02-27T12:42:49.000000Z",
"invitation_status": "accepted",
"acadle_invitation_status": null,
"roles": [
{
"id": 2,
"name": "ClinicAdmin"
}
]
},
{
"id": 295,
"mrn": "QF9H1FMQ1772196169",
"name": "Prof. Mitchell Toy V",
"email": "1772196169davis.jaunita@example.org",
"language": "en",
"phone": "640-880-3854",
"phone_country": "CI",
"phone_verified_at": null,
"address1": "9703 Roberts Avenue Apt. 041",
"address2": "Dariontown, KS 10958",
"postal_code": "26196-4787",
"city": "Bartell, O'Connell and Tremblay",
"country": "SE",
"clinic_name": "New Dominiquemouth",
"clinic_location": "10598 Presley Island\nWest Ed, HI 86968",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:49.000000Z",
"updated_at": "2026-02-27T12:42:49.000000Z",
"invitation_status": null,
"acadle_invitation_status": "accepted",
"roles": [
{
"id": 6,
"name": "AcadleUser"
}
]
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list available participants",
"code": "CHAT:LIST_PARTICIPANTS:INSUFFICIENT_PERMISSION"
}
Example response (404, Chat room not found):
{
"message": "Chat room not found",
"code": "CHAT:LIST_PARTICIPANTS:ROOM_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Config
API endpoints for device config management
Get device config
requires authentication
Definitions:
- config - current config entries
- config history entry - set of changes in config, updated during the session
- config history change - single change made to config (part of config history entry)
Example request:
curl --request GET \
--get "http://localhost:8000/api/device/1/config?_format=nulla" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/config"
);
const params = {
"_format": "nulla",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, Normal/compact response):
{
"common": {
"gripPairsConfig": [
1,
4,
2,
3,
6,
7,
9,
8
],
"controlConfig": [
0,
1,
0,
0,
0
],
"emgThresholds": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"interval": [
100
],
"gripSequentialConfig": [
1,
2,
4,
3,
0,
255,
6,
7,
9,
8,
255,
255
]
},
"modes": [
{
"id": 100,
"name": "Mode 1",
"slot": 0,
"config": {
"interval": [
300
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
},
{
"id": 101,
"name": "Mode 2",
"slot": 1,
"config": {
"interval": [
400
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
},
{
"id": 102,
"name": "Mode 3",
"slot": 2,
"config": {
"interval": [
500
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
}
]
}
Example response (200):
[
{
"id": 1,
"device_id": 14,
"mode_id": 1,
"key": "possimus",
"value": "tempore",
"created_at": "2026-02-27T12:42:26.000000Z",
"updated_at": "2026-02-27T12:42:26.000000Z",
"mode": {
"id": 1,
"device_id": 15,
"slot": null,
"name": "Nam aut quis sit rerum.",
"active": 1,
"created_at": "2026-02-27T12:42:26.000000Z",
"updated_at": "2026-02-27T12:42:26.000000Z"
}
},
{
"id": 2,
"device_id": 16,
"mode_id": 2,
"key": "magni",
"value": "est",
"created_at": "2026-02-27T12:42:26.000000Z",
"updated_at": "2026-02-27T12:42:26.000000Z",
"mode": {
"id": 2,
"device_id": 17,
"slot": null,
"name": "Natus unde nihil saepe exercitationem ex voluptas enim.",
"active": 0,
"created_at": "2026-02-27T12:42:26.000000Z",
"updated_at": "2026-02-27T12:42:26.000000Z"
}
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view device config",
"code": "CONFIG:GET:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG:GET:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update device config
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/device/1/config" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Remote session 2022-05-30\",
\"common\": \"{\\\"gripPairsConfig\\\": [1, 4, 2, 3, 6, 7, 9, 8], \\\"controlConfig\\\": [0, 1, 0, 0, 0], \\\"gripSequentialConfig\\\": [1, 2, 4, 3, 0, 255, 6, 7, 9, 8, 255, 255]\",
\"updateNote\": true,
\"modes\": [
{
\"id\": 1,
\"config\": \"{\\\"gripPairsConfig\\\": [1, 4, 2, 3, 6, 7, 9, 8], \\\"controlConfig\\\": [0, 1, 0, 0, 0], \\\"gripSequentialConfig\\\": [1, 2, 4, 3, 0, 255, 6, 7, 9, 8, 255, 255]\"
}
]
}"
const url = new URL(
"http://localhost:8000/api/device/1/config"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Remote session 2022-05-30",
"common": "{\"gripPairsConfig\": [1, 4, 2, 3, 6, 7, 9, 8], \"controlConfig\": [0, 1, 0, 0, 0], \"gripSequentialConfig\": [1, 2, 4, 3, 0, 255, 6, 7, 9, 8, 255, 255]",
"updateNote": true,
"modes": [
{
"id": 1,
"config": "{\"gripPairsConfig\": [1, 4, 2, 3, 6, 7, 9, 8], \"controlConfig\": [0, 1, 0, 0, 0], \"gripSequentialConfig\": [1, 2, 4, 3, 0, 255, 6, 7, 9, 8, 255, 255]"
}
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"common": {
"gripPairsConfig": [
1,
4,
2,
3,
6,
7,
9,
8
],
"controlConfig": [
0,
1,
0,
0,
0
],
"emgThresholds": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"interval": [
100
],
"gripSequentialConfig": [
1,
2,
4,
3,
0,
255,
6,
7,
9,
8,
255,
255
]
},
"modes": [
{
"id": 100,
"name": "Mode 1",
"slot": 0,
"config": {
"interval": [
300
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
},
{
"id": 101,
"name": "Mode 2",
"slot": 1,
"config": {
"interval": [
400
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
},
{
"id": 102,
"name": "Mode 3",
"slot": 2,
"config": {
"interval": [
500
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update device config",
"code": "CONFIG:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG:UPDATE:DEVICE_NOT_FOUND"
}
Example response (422, Invalid config):
{
"message": "Config has some problems and cannot be saved.",
"errors": {
"modes": {
"mode_3": "Config mode 3 does not belong to device 12."
},
"values": {
"common.inputSite": "Invalid value [\"11\"] for key inputSite - contains string values.",
"common.gripsPositions.1.initial": "Invalid value [200,\"100\",\"100\",\"100\",\"100\"] for key gripsPositions.1.initial - contains string values.",
"mode_1.inputSite": "Invalid value [\"11\"] for key inputSite - contains string values.",
"mode_1.gripsPositions.0.initial": "Invalid value [\"200\",\"100\",\"100\",\"100\",\"100\"] for key gripsPositions.1.initial - contains string values."
}
},
"code": "CONFIG:UPDATE:INVALID_CONFIG"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get device config history
requires authentication
For amputees only restore points are returned.
Example request:
curl --request GET \
--get "http://localhost:8000/api/device/1/config/history?restore_point=1&factory_reset_point=1&date_from=1642003200&date_to=1642003200" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"restore_point\": false,
\"factory_reset_point\": true
}"
const url = new URL(
"http://localhost:8000/api/device/1/config/history"
);
const params = {
"restore_point": "1",
"factory_reset_point": "1",
"date_from": "1642003200",
"date_to": "1642003200",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"restore_point": false,
"factory_reset_point": true
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Normal/compact response):
{
"common": {
"gripPairsConfig": [
1,
4,
2,
3,
6,
7,
9,
8
],
"controlConfig": [
0,
1,
0,
0,
0
],
"emgThresholds": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"interval": [
100
],
"gripSequentialConfig": [
1,
2,
4,
3,
0,
255,
6,
7,
9,
8,
255,
255
]
},
"modes": [
{
"id": 100,
"name": "Mode 1",
"slot": 0,
"config": {
"interval": [
300
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
},
{
"id": 101,
"name": "Mode 2",
"slot": 1,
"config": {
"interval": [
400
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
},
{
"id": 102,
"name": "Mode 3",
"slot": 2,
"config": {
"interval": [
500
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
}
]
}
Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"device_id": 18,
"index": null,
"name": "Ea sit sit occaecati enim reprehenderit omnis.",
"config": "{\"common\":{\"fingerStrength\":[1,300],\"gripPositions\":{\"_\":0,\"0\":{\"initial\":[75,20,21,13,30],\"limit\":[94,29,76,69,73]},\"1\":{\"initial\":[5,15,77,22,13],\"limit\":[87,28,86,47,28]},\"2\":{\"initial\":[21,45,23,28,61],\"limit\":[66,62,81,69,69]},\"3\":{\"initial\":[7,9,7,47,35],\"limit\":[19,80,70,56,55]},\"4\":{\"initial\":[42,51,32,5,29],\"limit\":[43,84,81,41,41]},\"5\":{\"initial\":[49,64,56,59,59],\"limit\":[56,72,71,64,59]},\"6\":{\"initial\":[50,4,10,20,80],\"limit\":[84,68,26,94,80]},\"7\":{\"initial\":[45,28,1,37,5],\"limit\":[80,51,60,56,75]},\"8\":{\"initial\":[55,62,10,24,43],\"limit\":[83,93,33,36,49]},\"9\":{\"initial\":[20,30,25,42,1],\"limit\":[72,31,36,59,21]},\"10\":{\"initial\":[52,51,31,12,64],\"limit\":[67,53,77,89,93]},\"11\":{\"initial\":[45,28,29,72,59],\"limit\":[75,56,44,87,92]},\"12\":{\"initial\":[50,3,39,4,61],\"limit\":[77,66,52,86,88]},\"13\":{\"initial\":[22,26,15,21,13],\"limit\":[37,29,19,93,18]}},\"inputSite\":[1]},\"modes\":[{\"id\":3,\"name\":\"Voluptas tempora recusandae at ut optio enim.\",\"slot\":0,\"config\":{\"autoGrasp\":[0,0],\"coContractionTimings\":[400,200],\"controlMode\":[0],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[30,60,100,30,80,0,10,0,90,30],\"gripPairsConfig\":[1,4,13,2,3,10,11,6],\"gripSequentialConfig\":[7,255,255,13,5,8,9,4,255,11,1,6],\"gripSwitchingMode\":[2],\"holdOpen\":[1500,2500],\"pulseTimings\":[290,440,340,1000],\"softGrip\":[0],\"speedControlStrategy\":[1]}},{\"id\":4,\"name\":\"Illum ipsam ratione nihil amet laudantium cum et et.\",\"slot\":1,\"config\":{\"autoGrasp\":[0,0],\"coContractionTimings\":[400,200],\"controlMode\":[1],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[70,0,30,60,0,40,80,30,80,50],\"gripPairsConfig\":[1,11,10,5,7,13,3,8],\"gripSequentialConfig\":[12,4,5,255,13,11,3,255,10,7,8,2],\"gripSwitchingMode\":[1],\"holdOpen\":[1500,2000],\"pulseTimings\":[510,490,550,570],\"softGrip\":[1],\"speedControlStrategy\":[1]}},{\"id\":5,\"name\":\"Officia nemo atque est et necessitatibus.\",\"slot\":2,\"config\":{\"autoGrasp\":[1,100],\"coContractionTimings\":[400,300],\"controlMode\":[0],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[50,10,40,60,30,10,0,30,100,50],\"gripPairsConfig\":[4,12,9,10,5,3,1,2],\"gripSequentialConfig\":[13,3,7,255,12,9,255,2,1,5,11,6],\"gripSwitchingMode\":[3],\"holdOpen\":[2500,2500],\"pulseTimings\":[370,130,610,720],\"softGrip\":[0],\"speedControlStrategy\":[1]}}]}",
"restore_point": 0,
"factory_reset_point": 0,
"changed_by": 46,
"created_at": "2026-02-27T12:42:27.000000Z",
"updated_at": "2026-02-27T12:42:27.000000Z",
"author": {
"id": 46,
"mrn": "SSJB35MR1772196147",
"name": "Dr. Tessie Marquardt III",
"email": "1772196147zritchie@example.net",
"language": "en",
"phone": "+17655469225",
"phone_country": "BH",
"phone_verified_at": null,
"address1": "6043 Bo Station Suite 005",
"address2": "Emilieport, VT 10695-1613",
"postal_code": "01300-5588",
"city": "Zboncak Ltd",
"country": "IT",
"clinic_name": "Haneport",
"clinic_location": "44272 Rempel Centers\nLake Braedenfurt, KS 82795",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:27.000000Z",
"updated_at": "2026-02-27T12:42:27.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"entries": [
{
"id": 1,
"config_history_id": 1,
"config_id": 3,
"old_value": "maiores",
"new_value": "rerum",
"created_at": "2026-02-27T12:42:27.000000Z",
"updated_at": "2026-02-27T12:42:27.000000Z",
"config_entry": {
"id": 3,
"device_id": 26,
"mode_id": null,
"key": "repellat",
"value": "odit",
"created_at": "2026-02-27T12:42:27.000000Z",
"updated_at": "2026-02-27T12:42:27.000000Z"
}
}
]
},
{
"id": 3,
"device_id": 27,
"index": null,
"name": "Aperiam ut natus voluptatum laborum facilis aspernatur possimus vel.",
"config": "{\"common\":{\"fingerStrength\":[1,500],\"gripPositions\":{\"_\":0,\"0\":{\"initial\":[17,11,80,43,80],\"limit\":[72,79,95,61,92]},\"1\":{\"initial\":[12,83,8,16,47],\"limit\":[35,86,45,77,51]},\"2\":{\"initial\":[8,13,5,41,31],\"limit\":[9,86,68,69,48]},\"3\":{\"initial\":[35,61,43,55,50],\"limit\":[69,86,83,62,73]},\"4\":{\"initial\":[36,41,55,43,19],\"limit\":[62,55,63,43,55]},\"5\":{\"initial\":[25,24,7,35,38],\"limit\":[52,94,66,54,44]},\"6\":{\"initial\":[31,12,5,2,2],\"limit\":[41,73,55,62,14]},\"7\":{\"initial\":[46,59,21,1,11],\"limit\":[52,71,72,46,27]},\"8\":{\"initial\":[50,5,30,26,8],\"limit\":[74,93,86,95,26]},\"9\":{\"initial\":[4,11,79,16,53],\"limit\":[23,62,89,34,66]},\"10\":{\"initial\":[13,24,42,61,51],\"limit\":[28,35,91,84,68]},\"11\":{\"initial\":[43,39,16,29,5],\"limit\":[78,58,47,67,26]},\"12\":{\"initial\":[22,46,12,80,74],\"limit\":[95,62,38,87,80]},\"13\":{\"initial\":[12,21,25,55,59],\"limit\":[68,54,76,60,89]}},\"inputSite\":[1]},\"modes\":[{\"id\":9,\"name\":\"Ex voluptatem tenetur asperiores vel.\",\"slot\":0,\"config\":{\"autoGrasp\":[0,0],\"coContractionTimings\":[400,200],\"controlMode\":[1],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[90,100,30,90,50,20,0,80,100,10],\"gripPairsConfig\":[12,10,11,2,5,13,8,3],\"gripSequentialConfig\":[3,255,255,255,12,8,2,255,10,9,11,255],\"gripSwitchingMode\":[2],\"holdOpen\":[1500,2000],\"pulseTimings\":[810,960,990,60],\"softGrip\":[0],\"speedControlStrategy\":[0]}},{\"id\":10,\"name\":\"Itaque voluptatibus ullam similique autem vero.\",\"slot\":1,\"config\":{\"autoGrasp\":[0,100],\"coContractionTimings\":[400,400],\"controlMode\":[0],\"emgGains\":[100,100],\"emgSpike\":[1,300],\"emgThresholds\":[60,70,30,70,70,70,40,0,0,60],\"gripPairsConfig\":[11,9,7,1,2,6,12,13],\"gripSequentialConfig\":[9,1,12,4,255,255,11,255,13,255,8,3],\"gripSwitchingMode\":[2],\"holdOpen\":[2000,2000],\"pulseTimings\":[210,810,390,750],\"softGrip\":[0],\"speedControlStrategy\":[1]}},{\"id\":11,\"name\":\"Praesentium iusto blanditiis debitis quaerat consequatur.\",\"slot\":2,\"config\":{\"autoGrasp\":[0,0],\"coContractionTimings\":[400,100],\"controlMode\":[1],\"emgGains\":[100,100],\"emgSpike\":[1,300],\"emgThresholds\":[0,50,60,90,80,60,50,40,90,50],\"gripPairsConfig\":[2,9,11,3,13,5,6,12],\"gripSequentialConfig\":[6,8,4,12,255,13,255,9,5,1,255,11],\"gripSwitchingMode\":[2],\"holdOpen\":[1500,2000],\"pulseTimings\":[70,870,330,850],\"softGrip\":[1],\"speedControlStrategy\":[1]}}]}",
"restore_point": 0,
"factory_reset_point": 0,
"changed_by": 49,
"created_at": "2026-02-27T12:42:27.000000Z",
"updated_at": "2026-02-27T12:42:27.000000Z",
"author": {
"id": 49,
"mrn": "UHCP7TH01772196147",
"name": "Mr. Curt Labadie",
"email": "1772196147vernice.oconnell@example.com",
"language": "en",
"phone": "(810) 322-5180",
"phone_country": "MF",
"phone_verified_at": null,
"address1": "75560 Sporer Rapids Suite 294",
"address2": "Port Anjalifort, MT 52441",
"postal_code": "73614-7078",
"city": "Bashirian Group",
"country": "GB",
"clinic_name": "Langfurt",
"clinic_location": "421 Jacobs Vista\nMargotport, MD 29757-4212",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:27.000000Z",
"updated_at": "2026-02-27T12:42:27.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"entries": [
{
"id": 2,
"config_history_id": 3,
"config_id": 4,
"old_value": "quibusdam",
"new_value": "ratione",
"created_at": "2026-02-27T12:42:27.000000Z",
"updated_at": "2026-02-27T12:42:27.000000Z",
"config_entry": {
"id": 4,
"device_id": 35,
"mode_id": null,
"key": "voluptas",
"value": "omnis",
"created_at": "2026-02-27T12:42:27.000000Z",
"updated_at": "2026-02-27T12:42:27.000000Z"
}
}
]
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view device config",
"code": "CONFIG:HISTORY:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG:HISTORY:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get device config history entry
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/device/1/config/history/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/config/history/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 5,
"device_id": 36,
"index": null,
"name": "Ea ex consequatur accusantium perferendis vel in ut.",
"config": "{\"common\":{\"fingerStrength\":[1,300],\"gripPositions\":{\"_\":0,\"0\":{\"initial\":[4,20,51,10,17],\"limit\":[20,55,81,63,41]},\"1\":{\"initial\":[35,77,24,1,18],\"limit\":[95,93,64,9,74]},\"2\":{\"initial\":[42,26,38,21,3],\"limit\":[64,66,73,56,4]},\"3\":{\"initial\":[23,23,12,16,51],\"limit\":[85,41,61,19,89]},\"4\":{\"initial\":[2,11,12,44,8],\"limit\":[31,34,84,78,77]},\"5\":{\"initial\":[49,15,41,5,68],\"limit\":[54,91,80,37,86]},\"6\":{\"initial\":[13,52,46,54,22],\"limit\":[48,70,94,79,95]},\"7\":{\"initial\":[58,40,33,33,14],\"limit\":[77,49,43,83,26]},\"8\":{\"initial\":[18,45,85,8,65],\"limit\":[41,56,87,89,79]},\"9\":{\"initial\":[76,40,56,74,42],\"limit\":[83,48,66,89,76]},\"10\":{\"initial\":[18,55,7,6,41],\"limit\":[20,90,91,29,86]},\"11\":{\"initial\":[3,46,11,38,42],\"limit\":[26,82,27,70,84]},\"12\":{\"initial\":[58,10,74,15,55],\"limit\":[84,19,92,90,56]},\"13\":{\"initial\":[2,2,1,33,20],\"limit\":[89,48,92,74,74]}},\"inputSite\":[0]},\"modes\":[{\"id\":15,\"name\":\"Laborum modi veniam laudantium provident.\",\"slot\":0,\"config\":{\"autoGrasp\":[1,100],\"coContractionTimings\":[500,500],\"controlMode\":[1],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[40,20,20,0,70,80,100,0,10,20],\"gripPairsConfig\":[13,2,4,7,12,6,8,5],\"gripSequentialConfig\":[255,12,8,255,10,255,255,13,3,255,11,255],\"gripSwitchingMode\":[1],\"holdOpen\":[1500,2000],\"pulseTimings\":[540,30,890,740],\"softGrip\":[1],\"speedControlStrategy\":[0]}},{\"id\":16,\"name\":\"Ipsa molestiae placeat et dolore expedita similique aut.\",\"slot\":1,\"config\":{\"autoGrasp\":[0,0],\"coContractionTimings\":[300,200],\"controlMode\":[1],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[90,80,100,40,20,10,0,40,50,20],\"gripPairsConfig\":[13,5,6,2,3,12,8,9],\"gripSequentialConfig\":[4,13,10,6,3,2,255,12,9,5,255,8],\"gripSwitchingMode\":[1],\"holdOpen\":[2000,2000],\"pulseTimings\":[810,860,800,740],\"softGrip\":[0],\"speedControlStrategy\":[0]}},{\"id\":17,\"name\":\"Vel ea harum eos recusandae ducimus perspiciatis.\",\"slot\":2,\"config\":{\"autoGrasp\":[1,0],\"coContractionTimings\":[200,200],\"controlMode\":[1],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[90,50,80,80,70,40,10,60,70,90],\"gripPairsConfig\":[6,10,5,3,12,8,1,2],\"gripSequentialConfig\":[255,9,7,255,255,255,4,6,10,255,255,255],\"gripSwitchingMode\":[1],\"holdOpen\":[1500,2000],\"pulseTimings\":[680,410,980,610],\"softGrip\":[0],\"speedControlStrategy\":[1]}}]}",
"restore_point": 1,
"factory_reset_point": 0,
"changed_by": 51,
"created_at": "2026-02-27T12:42:27.000000Z",
"updated_at": "2026-02-27T12:42:27.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view device config",
"code": "CONFIG:HISTORY_ENTRY:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG:HISTORY_ENTRY:DEVICE_NOT_FOUND"
}
Example response (404, Config history entry not found):
{
"message": "Config history entry not found",
"code": "CONFIG:HISTORY_ENTRY:HISTORY_ENTRY_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update config history
requires authentication
Returns updated config history in response.
Example request:
curl --request POST \
"http://localhost:8000/api/device/1/config/history/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Remote session 2022-05-30\",
\"restore_point\": true,
\"factory_reset_point\": false
}"
const url = new URL(
"http://localhost:8000/api/device/1/config/history/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Remote session 2022-05-30",
"restore_point": true,
"factory_reset_point": false
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 6,
"device_id": 40,
"index": null,
"name": "Voluptatibus rerum velit ut praesentium.",
"config": "{\"common\":{\"fingerStrength\":[1,400],\"gripPositions\":{\"_\":0,\"0\":{\"initial\":[54,20,1,6,88],\"limit\":[95,51,17,66,95]},\"1\":{\"initial\":[27,36,31,2,68],\"limit\":[82,41,88,13,69]},\"2\":{\"initial\":[11,14,46,16,16],\"limit\":[21,20,55,89,32]},\"3\":{\"initial\":[3,80,18,43,18],\"limit\":[80,92,26,48,44]},\"4\":{\"initial\":[67,10,30,2,41],\"limit\":[68,73,85,5,68]},\"5\":{\"initial\":[54,38,22,4,56],\"limit\":[76,81,50,93,78]},\"6\":{\"initial\":[17,9,32,14,11],\"limit\":[81,89,52,72,89]},\"7\":{\"initial\":[40,54,22,25,16],\"limit\":[92,74,38,75,75]},\"8\":{\"initial\":[6,1,53,22,39],\"limit\":[74,49,68,63,64]},\"9\":{\"initial\":[30,9,21,30,9],\"limit\":[50,22,52,65,78]},\"10\":{\"initial\":[58,45,64,35,83],\"limit\":[63,69,92,51,91]},\"11\":{\"initial\":[27,17,47,41,39],\"limit\":[56,60,75,56,68]},\"12\":{\"initial\":[2,43,69,18,5],\"limit\":[90,49,78,86,93]},\"13\":{\"initial\":[34,33,48,26,59],\"limit\":[70,41,90,89,89]}},\"inputSite\":[1]},\"modes\":[{\"id\":18,\"name\":\"Nisi minus nihil hic nihil consequuntur animi non.\",\"slot\":0,\"config\":{\"autoGrasp\":[0,0],\"coContractionTimings\":[400,100],\"controlMode\":[0],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[30,60,90,80,100,80,50,80,20,80],\"gripPairsConfig\":[1,4,11,8,10,13,12,9],\"gripSequentialConfig\":[3,4,7,8,5,12,9,6,10,11,1,13],\"gripSwitchingMode\":[2],\"holdOpen\":[2000,2500],\"pulseTimings\":[300,740,120,80],\"softGrip\":[1],\"speedControlStrategy\":[0]}},{\"id\":19,\"name\":\"Sed deleniti odio qui aut quisquam necessitatibus ducimus voluptas.\",\"slot\":1,\"config\":{\"autoGrasp\":[1,0],\"coContractionTimings\":[400,100],\"controlMode\":[1],\"emgGains\":[100,100],\"emgSpike\":[1,300],\"emgThresholds\":[70,80,90,10,0,80,10,100,10,60],\"gripPairsConfig\":[2,5,3,13,10,1,9,7],\"gripSequentialConfig\":[255,1,11,6,5,9,255,7,3,12,8,2],\"gripSwitchingMode\":[2],\"holdOpen\":[1500,2000],\"pulseTimings\":[650,100,230,480],\"softGrip\":[1],\"speedControlStrategy\":[1]}},{\"id\":20,\"name\":\"Sed qui necessitatibus illo molestiae.\",\"slot\":2,\"config\":{\"autoGrasp\":[1,100],\"coContractionTimings\":[200,100],\"controlMode\":[0],\"emgGains\":[100,100],\"emgSpike\":[1,300],\"emgThresholds\":[40,30,60,80,0,50,40,50,70,30],\"gripPairsConfig\":[1,9,4,13,6,7,8,11],\"gripSequentialConfig\":[255,255,3,12,13,255,5,10,4,255,255,2],\"gripSwitchingMode\":[3],\"holdOpen\":[1500,2500],\"pulseTimings\":[790,540,660,90],\"softGrip\":[0],\"speedControlStrategy\":[0]}}]}",
"restore_point": 1,
"factory_reset_point": 0,
"changed_by": 52,
"created_at": "2026-02-27T12:42:27.000000Z",
"updated_at": "2026-02-27T12:42:27.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update device config",
"code": "CONFIG:HISTORY_UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (403, Factory reset point already exists):
{
"message": "Factory reset point does not exist",
"code": "CONFIG:HISTORY_UPDATE:FACTORY_RESET_POINT_ALREADY_EXISTS"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG:HISTORY_UPDATE:DEVICE_NOT_FOUND"
}
Example response (404, Config history entry not found):
{
"message": "Config history entry not found",
"code": "CONFIG:HISTORY_UPDATE:HISTORY_ENTRY_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Undo single config history change
requires authentication
Returns updated config in response.
Example request:
curl --request DELETE \
"http://localhost:8000/api/device/1/config/history/undo/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/config/history/undo/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, Normal/compact response):
{
"common": {
"gripPairsConfig": [
1,
4,
2,
3,
6,
7,
9,
8
],
"controlConfig": [
0,
1,
0,
0,
0
],
"emgThresholds": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"interval": [
100
],
"gripSequentialConfig": [
1,
2,
4,
3,
0,
255,
6,
7,
9,
8,
255,
255
]
},
"modes": [
{
"id": 100,
"name": "Mode 1",
"slot": 0,
"config": {
"interval": [
300
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
},
{
"id": 101,
"name": "Mode 2",
"slot": 1,
"config": {
"interval": [
400
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
},
{
"id": 102,
"name": "Mode 3",
"slot": 2,
"config": {
"interval": [
500
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update device config",
"code": "CONFIG:UNDO:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG:UNDO:DEVICE_NOT_FOUND"
}
Example response (404, Config history entry not found):
{
"message": "Config history entry not found",
"code": "CONFIG:UNDO:HISTORY_ENTRY_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Restore config history entry
requires authentication
Restores config from given config history entry (all changes). Sends support ticket if patient is assigned to device, returns config instead.
Example request:
curl --request POST \
"http://localhost:8000/api/device/1/config/restore/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/config/restore/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200, Patient not assigned, returns config):
{
"common": {
"gripPairsConfig": [
1,
4,
2,
3,
6,
7,
9,
8
],
"controlConfig": [
0,
1,
0,
0,
0
],
"emgThresholds": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"interval": [
100
],
"gripSequentialConfig": [
1,
2,
4,
3,
0,
255,
6,
7,
9,
8,
255,
255
]
},
"modes": [
{
"id": 100,
"name": "Mode 1",
"slot": 0,
"config": {
"interval": [
300
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
},
{
"id": 101,
"name": "Mode 2",
"slot": 1,
"config": {
"interval": [
400
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
},
{
"id": 102,
"name": "Mode 3",
"slot": 2,
"config": {
"interval": [
500
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
}
]
}
Example response (202):
{
"id": 1,
"sender_id": 53,
"recipient_id": 54,
"device_id": null,
"meeting_date": "2026-02-27 12:42:27",
"meeting_type": "online_meeting",
"contact_email": "lenore.nitzsche@kunde.net",
"status": "new",
"created_at": "2026-02-27T12:42:28.000000Z",
"updated_at": "2026-02-27T12:42:28.000000Z",
"sender": {
"id": 53,
"mrn": "ZYRM2M9T1772196147",
"name": "Dr. Sanford Bradtke",
"email": "1772196147shields.orpha@example.com",
"language": "en",
"phone": "+1-681-455-5352",
"phone_country": "RU",
"phone_verified_at": null,
"address1": "572 Bennett Fords Apt. 876",
"address2": "Jarretbury, WV 32544-2806",
"postal_code": "55161",
"city": "Windler-Gleichner",
"country": "US",
"clinic_name": "South Kaiastad",
"clinic_location": "13155 Wolf Plain\nEast Dora, MI 75457-6350",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:27.000000Z",
"updated_at": "2026-02-27T12:42:27.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"recipient": {
"id": 54,
"mrn": "P6QCJBKM1772196147",
"name": "Destany Gleichner",
"email": "1772196147edgar78@example.net",
"language": "en",
"phone": "+1-940-287-4828",
"phone_country": "NE",
"phone_verified_at": null,
"address1": "4194 Cornelius Spur Apt. 744",
"address2": "Christiansenbury, DE 37406",
"postal_code": "25835",
"city": "Boyer LLC",
"country": "PL",
"clinic_name": "East Nick",
"clinic_location": "536 Casper Skyway\nFramifort, IN 36042-5799",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:28.000000Z",
"updated_at": "2026-02-27T12:42:28.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"device": null,
"messages": [
{
"id": 1,
"ticket_id": 1,
"sender_id": 55,
"title": "Dr.",
"content": "Perferendis ullam et ut suscipit et et.",
"is_read": false,
"created_at": "2026-02-27T12:42:28.000000Z",
"updated_at": "2026-02-27T12:42:28.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update device config",
"code": "CONFIG:RESTORE:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG:RESTORE:DEVICE_NOT_FOUND"
}
Example response (404, Config history entry not found):
{
"message": "Config history entry not found",
"code": "CONFIG:RESTORE:HISTORY_ENTRY_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Restore to factory reset point
requires authentication
Restores config from the device's factory reset point. Sends a support ticket if the patient is assigned to the device. Returns the array that contains:
config- The factory reset config. It might be updated with current config entries when the restored config does not contain a key or its value is false, but the key is available in the current config, has a non-false value, and is required by the config schema.not_modified- The part of the current config that contains keys which were ignored (because they’re on the ignore list, such as custom grips settings), or were not updated with values from the factory reset config (because the values are the same in both configs, or missing in the factory reset config but present and non-false in the current config). These are included in theconfigto ensure their values remain unchanged and are not replaced with defaults.ticket- Support ticket entity, if patient is assigned, null otherwise.
Example request:
curl --request POST \
"http://localhost:8000/api/device/1/config/restore-factory-reset" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/config/restore-factory-reset"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200, OK):
{
"config": {
"common": {
"inputSite": [
1
],
"generalHandSettings": false,
"batteryBeep": [
1,
0
],
"emgGains": false,
"autoGrasp": false
},
"modes": [
{
"id": 1,
"name": "Mode 0",
"slot": 0,
"config": {
"gripPairsConfig": false,
"emgThresholds": false,
"emgSpike": false,
"controlMode": false
}
},
{
"id": 1530,
"name": "Mode 1",
"slot": 1,
"config": {
"gripPairsConfig": false,
"emgThresholds": false,
"emgSpike": false,
"controlMode": false
}
},
{
"id": 1531,
"name": "Mode 2",
"slot": 2,
"config": {
"gripPairsConfig": false,
"emgThresholds": false,
"emgSpike": false,
"controlMode": false
}
}
]
},
"not_modified": {
"common": {
"inputSite": [
1
],
"batteryBeep": [
1,
0
],
"generalHandSettings": [
1,
2,
3,
4
]
},
"modes": [
{
"userFeedbackType": false,
"buzzingVolumeSettings": false
},
{
"userFeedbackType": false,
"buzzingVolumeSettings": false
},
{
"userFeedbackType": false,
"buzzingVolumeSettings": false
}
]
},
"ticket": {
"id": 1,
"sender_id": 1,
"recipient_id": 2,
"device_id": 1,
"meeting_date": "2025-07-22T15:00:00.000000Z",
"meeting_type": "none",
"contact_email": null,
"status": "new",
"created_at": "2025-07-22T15:00:00.000000Z",
"updated_at": "2025-07-22T15:00:00.000000Z",
"messages": [
{
"id": 1,
"ticket_id": 1,
"sender_id": 1,
"title": "New config update",
"content": "",
"is_read": false,
"created_at": "2025-07-22T15:00:00.000000Z",
"updated_at": "2025-07-22T15:00:00.000000Z",
"attachments": [
{
"id": 6629,
"ticket_id": 12973,
"ticket_message_id": 6517,
"type": "json",
"title": "Current config",
"attachment": "{\"common\":{},\"modes\":[{\"id\":1,\"name\":\"Mode 0\",\"slot\":0,\"config\":{}},{\"id\":2,\"name\":\"Mode 1\",\"slot\":1,\"config\":{}},{\"id\":3,\"name\":\"Mode 2\",\"slot\":2,\"config\":{}}]}",
"created_at": "2025-07-22T15:00:00.000000Z",
"updated_at": "2025-07-22T15:00:00.000000Z"
},
{
"id": 6630,
"ticket_id": 12973,
"ticket_message_id": 6517,
"type": "json",
"title": "New config",
"attachment": "{\"common\":{},\"modes\":[{\"id\":1,\"name\":\"Mode 0\",\"slot\":0,\"config\":{}},{\"id\":2,\"name\":\"Mode 1\",\"slot\":1,\"config\":{}},{\"id\":3,\"name\":\"Mode 2\",\"slot\":2,\"config\":{}}]}",
"created_at": "2025-07-22T15:00:00.000000Z",
"updated_at": "2025-07-22T15:00:00.000000Z"
}
]
}
]
}
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update device config",
"code": "CONFIG:RESTORE_FACTORY_RESET:INSUFFICIENT_PERMISSION"
}
Example response (403, Config history entry not found):
{
"message": "Config history entry not found",
"code": "CONFIG:RESTORE_FACTORY_RESET:NO_RESTORE_POINT"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG:RESTORE_FACTORY_RESET:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Send test config
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/device/1/config/send" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"description\": \"Fixed problem with grips.\",
\"p2p_session\": 1,
\"updateConfig\": false,
\"common\": \"{\\\"gripPairsConfig\\\": [1, 4, 2, 3, 6, 7, 9, 8], \\\"controlConfig\\\": [0, 1, 0, 0, 0], \\\"gripSequentialConfig\\\": [1, 2, 4, 3, 0, 255, 6, 7, 9, 8, 255, 255]\",
\"modes\": [
{
\"id\": 1,
\"config\": \"{\\\"gripPairsConfig\\\": [1, 4, 2, 3, 6, 7, 9, 8], \\\"controlConfig\\\": [0, 1, 0, 0, 0], \\\"gripSequentialConfig\\\": [1, 2, 4, 3, 0, 255, 6, 7, 9, 8, 255, 255]\"
}
]
}"
const url = new URL(
"http://localhost:8000/api/device/1/config/send"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"description": "Fixed problem with grips.",
"p2p_session": 1,
"updateConfig": false,
"common": "{\"gripPairsConfig\": [1, 4, 2, 3, 6, 7, 9, 8], \"controlConfig\": [0, 1, 0, 0, 0], \"gripSequentialConfig\": [1, 2, 4, 3, 0, 255, 6, 7, 9, 8, 255, 255]",
"modes": [
{
"id": 1,
"config": "{\"gripPairsConfig\": [1, 4, 2, 3, 6, 7, 9, 8], \"controlConfig\": [0, 1, 0, 0, 0], \"gripSequentialConfig\": [1, 2, 4, 3, 0, 255, 6, 7, 9, 8, 255, 255]"
}
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 7,
"sender_id": 64,
"recipient_id": 65,
"device_id": null,
"meeting_date": "2026-02-27 12:42:28",
"meeting_type": "online_meeting",
"contact_email": "nolan.samara@yahoo.com",
"status": "new",
"created_at": "2026-02-27T12:42:28.000000Z",
"updated_at": "2026-02-27T12:42:28.000000Z",
"sender": {
"id": 64,
"mrn": "SI3LPL2Y1772196148",
"name": "Orlando Pollich",
"email": "1772196148dbeier@example.org",
"language": "en",
"phone": "947.246.0154",
"phone_country": "TK",
"phone_verified_at": null,
"address1": "844 Tom Stravenue Apt. 898",
"address2": "Myrachester, WA 49753-1528",
"postal_code": "29700",
"city": "Monahan, Beer and O'Conner",
"country": "MT",
"clinic_name": "Jalynshire",
"clinic_location": "286 Bins Parks Suite 907\nHilpertview, MA 00781-6811",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:28.000000Z",
"updated_at": "2026-02-27T12:42:28.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"recipient": {
"id": 65,
"mrn": "4AO69K8M1772196148",
"name": "Ellie Streich Sr.",
"email": "1772196148kertzmann.domenick@example.com",
"language": "en",
"phone": "(321) 544-2480",
"phone_country": "NE",
"phone_verified_at": null,
"address1": "6658 Hodkiewicz Ferry",
"address2": "Doylebury, IA 17439-6478",
"postal_code": "17072",
"city": "O'Connell, Boyer and Davis",
"country": "DE",
"clinic_name": "Blockberg",
"clinic_location": "747 D'Amore Mountains\nEast Katharina, AZ 66336",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:28.000000Z",
"updated_at": "2026-02-27T12:42:28.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"device": null,
"messages": [
{
"id": 4,
"ticket_id": 7,
"sender_id": 66,
"title": "Miss",
"content": "Eos natus ea dolor explicabo voluptatem perspiciatis illum eius.",
"is_read": false,
"created_at": "2026-02-27T12:42:29.000000Z",
"updated_at": "2026-02-27T12:42:29.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update device config",
"code": "CONFIG:SEND:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG:SEND:DEVICE_NOT_FOUND"
}
Example response (422, Device does not have an amputee assigned):
{
"message": "Device does not have an amputee assigned",
"code": "CONFIG:SEND:NO_PATIENT"
}
Example response (422, Invalid P2P session):
{
"message": "Invalid P2P session",
"code": "CONFIG:SEND:INVALID_P2P_SESSION"
}
Example response (422, Invalid config):
{
"message": "Config has some problems and cannot be saved.",
"errors": {
"modes": {
"mode_3": "Config mode 3 does not belong to device 12."
},
"values": {
"common.inputSite": "Invalid value [\"11\"] for key inputSite - contains string values.",
"common.gripsPositions.1.initial": "Invalid value [200,\"100\",\"100\",\"100\",\"100\"] for key gripsPositions.1.initial - contains string values.",
"mode_1.inputSite": "Invalid value [\"11\"] for key inputSite - contains string values.",
"mode_1.gripsPositions.0.initial": "Invalid value [\"200\",\"100\",\"100\",\"100\",\"100\"] for key gripsPositions.1.initial - contains string values."
}
},
"code": "CONFIG:SEND:INVALID_CONFIG"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Convert config
requires authentication
Convert config JSON to match given Firmware Version. Keys are moved between common config and modes.
Example request:
curl --request POST \
"http://localhost:8000/api/config/convert" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"config\": \"[\\\"possimus\\\",\\\"voluptatibus\\\"]\",
\"firmware\": 1
}"
const url = new URL(
"http://localhost:8000/api/config/convert"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"config": "[\"possimus\",\"voluptatibus\"]",
"firmware": 1
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"common": {
"gripPairsConfig": [
1,
4,
2,
3,
6,
7,
9,
8
],
"controlConfig": [
0,
1,
0,
0,
0
],
"emgThresholds": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"interval": [
100
],
"gripSequentialConfig": [
1,
2,
4,
3,
0,
255,
6,
7,
9,
8,
255,
255
]
},
"modes": [
{
"id": 100,
"name": "Mode 1",
"slot": 0,
"config": {
"interval": [
300
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
},
{
"id": 101,
"name": "Mode 2",
"slot": 1,
"config": {
"interval": [
400
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
},
{
"id": 102,
"name": "Mode 3",
"slot": 2,
"config": {
"interval": [
500
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update device config",
"code": "CONFIG:CONVERT:INSUFFICIENT_PERMISSION"
}
Example response (404, Firmware version not found):
{
"message": "Firmware version not found",
"code": "CONFIG:CONVERT:FIRMWARE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Config Demo
API endpoints for managing config demos
List config demos
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/device/1/config/demos?accepted=1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/config/demos"
);
const params = {
"accepted": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"device_id": 72,
"message_id": 8,
"config": "Et nulla non quis voluptatem et quia veritatis molestiae.",
"is_accepted": 0,
"notes": "Tempora rerum in consequatur quis ut enim eos.",
"created_at": "2026-02-27T12:42:30.000000Z",
"updated_at": "2026-02-27T12:42:30.000000Z",
"message": {
"id": 8,
"ticket_id": 15,
"sender_id": 87,
"title": "Miss",
"content": "Est labore dolorum officia facere.",
"is_read": false,
"created_at": "2026-02-27T12:42:30.000000Z",
"updated_at": "2026-02-27T12:42:30.000000Z"
}
},
{
"id": 2,
"device_id": 73,
"message_id": 10,
"config": "Aperiam ullam velit qui quas eum.",
"is_accepted": 0,
"notes": "Inventore quos nisi eos impedit.",
"created_at": "2026-02-27T12:42:31.000000Z",
"updated_at": "2026-02-27T12:42:31.000000Z",
"message": {
"id": 10,
"ticket_id": 18,
"sender_id": 92,
"title": "Dr.",
"content": "Vero qui voluptate perspiciatis.",
"is_read": false,
"created_at": "2026-02-27T12:42:31.000000Z",
"updated_at": "2026-02-27T12:42:31.000000Z"
}
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to access config demos",
"code": "CONFIG_DEMO:LIST:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG_DEMO:LIST:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update config demo
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/device/1/config/demos/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"is_accepted\": false,
\"notes\": \"Something is still not working\"
}"
const url = new URL(
"http://localhost:8000/api/device/1/config/demos/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"is_accepted": false,
"notes": "Something is still not working"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 3,
"device_id": 74,
"message_id": 11,
"config": "Rerum voluptas harum quia ut omnis.",
"is_accepted": 1,
"notes": "Tempora nesciunt amet qui placeat quod.",
"created_at": "2026-02-27T12:42:31.000000Z",
"updated_at": "2026-02-27T12:42:31.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to access config demos",
"code": "CONFIG_DEMO:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG_DEMO:UPDATE:DEVICE_NOT_FOUND"
}
Example response (404, Config demo not found):
{
"message": "Config demo not found",
"code": "CONFIG_DEMO:UPDATE:DEMO_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Config Modes
API endpoints for managing config modes
List config modes
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/device/1/config-modes" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/config-modes"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 72,
"device_id": 103,
"slot": null,
"name": "Odio doloribus dolor debitis aut animi.",
"active": 1,
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z",
"device": {
"id": 103,
"serial": "7f3c0f3b-afda-3736-93fe-f041138a5cb8",
"bluetooth_id": "6a9ad7bf-9355-33ca-b6c6-f5301f7a2260",
"company_id": null,
"model_id": null,
"amputee_id": 105,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z"
}
},
{
"id": 73,
"device_id": 105,
"slot": null,
"name": "Consequatur cupiditate impedit aliquid dolor sit dolorum.",
"active": 0,
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z",
"config": {}
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list config modes",
"code": "CONFIG_MODES:LIST:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG_MODES:LIST:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get config mode
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/device/1/config-modes/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/config-modes/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 74,
"device_id": 106,
"slot": null,
"name": "Corporis voluptatem adipisci ut esse vitae aut.",
"active": 0,
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list config modes",
"code": "CONFIG_MODES:GET:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG_MODES:GET:DEVICE_NOT_FOUND"
}
Example response (404, Config mode not found):
{
"message": "Config mode not found",
"code": "CONFIG_MODES:GET:MODE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create config mode
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/device/1/config-modes" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"slot\": 0,
\"name\": \"Sport mode\",
\"active\": true
}"
const url = new URL(
"http://localhost:8000/api/device/1/config-modes"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"slot": 0,
"name": "Sport mode",
"active": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 75,
"device_id": 107,
"slot": null,
"name": "Occaecati ab sed a illo dolor voluptatem.",
"active": 1,
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create config modes",
"code": "CONFIG_MODES:CREATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG_MODES:CREATE:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update config mode
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/device/1/config-modes/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"slot\": 0,
\"name\": \"Sport mode\",
\"active\": true
}"
const url = new URL(
"http://localhost:8000/api/device/1/config-modes/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"slot": 0,
"name": "Sport mode",
"active": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 76,
"device_id": 108,
"slot": null,
"name": "Officiis et ipsa alias quos doloremque dolore.",
"active": 1,
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update config mode",
"code": "CONFIG_MODES:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG_MODES:UPDATE:DEVICE_NOT_FOUND"
}
Example response (404, Config mode not found):
{
"message": "Config mode not found",
"code": "CONFIG_MODES:UPDATE:MODE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Copy device config from template
requires authentication
Copy config template into selected config mode. Sends support ticket if patient is assigned to device, returns config instead.
Example request:
curl --request POST \
"http://localhost:8000/api/device/1/config-modes/1/from-template/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/config-modes/1/from-template/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200, Patient not assigned, returns config):
{
"common": {
"gripPairsConfig": [
1,
4,
2,
3,
6,
7,
9,
8
],
"controlConfig": [
0,
1,
0,
0,
0
],
"emgThresholds": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"interval": [
100
],
"gripSequentialConfig": [
1,
2,
4,
3,
0,
255,
6,
7,
9,
8,
255,
255
]
},
"modes": [
{
"id": 100,
"name": "Mode 1",
"slot": 0,
"config": {
"interval": [
300
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
},
{
"id": 101,
"name": "Mode 2",
"slot": 1,
"config": {
"interval": [
400
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
},
{
"id": 102,
"name": "Mode 3",
"slot": 2,
"config": {
"interval": [
500
],
"fingerStrength": [
1,
100
],
"autoGrasp": [
0,
100
],
"emgSpike": [
0,
300
]
}
}
]
}
Example response (202):
{
"id": 21,
"sender_id": 107,
"recipient_id": 108,
"device_id": null,
"meeting_date": "2026-02-27 12:42:32",
"meeting_type": "online_meeting",
"contact_email": "barrows.skye@trantow.com",
"status": "new",
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z",
"sender": {
"id": 107,
"mrn": "NIPIPAHB1772196152",
"name": "Keon Zieme DVM",
"email": "1772196152gleichner.sister@example.org",
"language": "en",
"phone": "202-445-6576",
"phone_country": "GR",
"phone_verified_at": null,
"address1": "843 Altenwerth Spur",
"address2": "Kareemville, LA 97693-0061",
"postal_code": "72408",
"city": "Beahan, Luettgen and Yost",
"country": "LT",
"clinic_name": "West Madge",
"clinic_location": "8418 Stokes Square\nElmoreland, NC 94836-4104",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"recipient": {
"id": 108,
"mrn": "TH4K25QY1772196152",
"name": "Hallie Dickens",
"email": "1772196152khyatt@example.org",
"language": "en",
"phone": "(410) 329-4583",
"phone_country": "RE",
"phone_verified_at": null,
"address1": "5041 Jaron Circle Apt. 183",
"address2": "New Stephany, KS 67199",
"postal_code": "23585",
"city": "Bechtelar-Kuphal",
"country": "SK",
"clinic_name": "Port Ambroseberg",
"clinic_location": "56540 Maggio Drives\nWest Alison, NM 21425",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"device": null,
"messages": [
{
"id": 12,
"ticket_id": 21,
"sender_id": 109,
"title": "Miss",
"content": "Laudantium ut quo labore voluptas vitae accusamus.",
"is_read": false,
"created_at": "2026-02-27T12:42:33.000000Z",
"updated_at": "2026-02-27T12:42:33.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update config mode",
"code": "CONFIG_MODES:COPY_TEMPLATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG_MODES:COPY_TEMPLATE:DEVICE_NOT_FOUND"
}
Example response (404, Config mode not found):
{
"message": "Config mode not found",
"code": "CONFIG_MODES:COPY_TEMPLATE:MODE_NOT_FOUND"
}
Example response (404, Config template not found):
{
"message": "Config template not found",
"code": "CONFIG_MODES:COPY_TEMPLATE:TEMPLATE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Config Notes
API endpoints for config history notes
Get config entry notes list
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/device/1/config/1/notes?user=1&type=public" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/config/1/notes"
);
const params = {
"user": "1",
"type": "public",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"config_history_id": 7,
"user_id": 76,
"note": "Deleniti commodi id laudantium ullam et.",
"type": "public",
"created_at": "2026-02-27T12:42:29.000000Z",
"updated_at": "2026-02-27T12:42:29.000000Z",
"author": {
"id": 76,
"mrn": "ML6S9QQ51772196149",
"name": "Marina Moen",
"email": "1772196149stracke.wilhelmine@example.org",
"language": "en",
"phone": "(308) 450-7404",
"phone_country": "GA",
"phone_verified_at": null,
"address1": "624 Lakin Point",
"address2": "McClureton, GA 25062-1331",
"postal_code": "91348",
"city": "Rohan-Hilpert",
"country": "MT",
"clinic_name": "McClureville",
"clinic_location": "7064 Yundt Loop\nErniefort, NV 48131-5346",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:29.000000Z",
"updated_at": "2026-02-27T12:42:29.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
},
{
"id": 2,
"config_history_id": 8,
"user_id": 78,
"note": "Qui rem ratione assumenda eos.",
"type": "public",
"created_at": "2026-02-27T12:42:30.000000Z",
"updated_at": "2026-02-27T12:42:30.000000Z",
"author": {
"id": 78,
"mrn": "4ZVGS0GJ1772196149",
"name": "Rozella Ward",
"email": "1772196149crooks.heaven@example.com",
"language": "en",
"phone": "+1-564-826-7792",
"phone_country": "BB",
"phone_verified_at": null,
"address1": "44947 Elvis Plains",
"address2": "Klockoside, NH 87699-0296",
"postal_code": "49674-8109",
"city": "O'Keefe, Jast and O'Hara",
"country": "HU",
"clinic_name": "Lake Madelynfort",
"clinic_location": "2881 Christiansen Causeway Apt. 200\nOlsonbury, PA 14011",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:30.000000Z",
"updated_at": "2026-02-27T12:42:30.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to access config notes",
"code": "CONFIG_NOTES:LIST:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG_NOTES:LIST:DEVICE_NOT_FOUND"
}
Example response (404, Config history entry not found):
{
"message": "Config history entry not found",
"code": "CONFIG_NOTES:LIST:HISTORY_ENTRY_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get config entry note
requires authentication
Returns single config history entry note in response.
Example request:
curl --request GET \
--get "http://localhost:8000/api/device/1/config/1/notes/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/config/1/notes/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 3,
"config_history_id": 9,
"user_id": 80,
"note": "Quo alias accusantium perspiciatis.",
"type": "public",
"created_at": "2026-02-27T12:42:30.000000Z",
"updated_at": "2026-02-27T12:42:30.000000Z",
"author": {
"id": 80,
"mrn": "APZPETVK1772196150",
"name": "Margarett Shields",
"email": "1772196150alexys.hessel@example.org",
"language": "en",
"phone": "725-380-4959",
"phone_country": "TF",
"phone_verified_at": null,
"address1": "8262 Nicolas Motorway Apt. 113",
"address2": "Jasenland, FL 16022",
"postal_code": "75426",
"city": "Jakubowski LLC",
"country": "LV",
"clinic_name": "Ovaburgh",
"clinic_location": "2117 Luettgen Stravenue\nBoganbury, CT 21325",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:30.000000Z",
"updated_at": "2026-02-27T12:42:30.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to access config notes",
"code": "CONFIG_NOTES:GET_ENTRY:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG_NOTES:GET_ENTRY:DEVICE_NOT_FOUND"
}
Example response (404, Config history entry not found):
{
"message": "Config history entry not found",
"code": "CONFIG_NOTES:GET_ENTRY:HISTORY_ENTRY_NOT_FOUND"
}
Example response (404, Config history note not found):
{
"message": "Config history note not found",
"code": "CONFIG_NOTES:GET_ENTRY:HISTORY_NOTE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create config entry note
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/device/1/config/1/notes" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"note\": \"Error nesciunt laudantium sapiente eligendi enim vel.\",
\"type\": \"public\"
}"
const url = new URL(
"http://localhost:8000/api/device/1/config/1/notes"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"note": "Error nesciunt laudantium sapiente eligendi enim vel.",
"type": "public"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"id": 4,
"config_history_id": 10,
"user_id": 82,
"note": "Fugit quas rerum culpa magnam.",
"type": "public",
"created_at": "2026-02-27T12:42:30.000000Z",
"updated_at": "2026-02-27T12:42:30.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to add config notes",
"code": "CONFIG_NOTES:CREATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG_NOTES:CREATE:DEVICE_NOT_FOUND"
}
Example response (404, Config history entry not found):
{
"message": "Config history entry not found",
"code": "CONFIG_NOTES:CREATE:HISTORY_ENTRY_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete config note
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/device/1/config/1/notes/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/config/1/notes/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Config history note deleted",
"code": "CONFIG_NOTES:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to delete config notes",
"code": "CONFIG_NOTES:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CONFIG_NOTES:DELETE:DEVICE_NOT_FOUND"
}
Example response (404, Config history entry not found):
{
"message": "Config history entry not found",
"code": "CONFIG_NOTES:DELETE:HISTORY_ENTRY_NOT_FOUND"
}
Example response (404, Config history note not found):
{
"message": "Config history note not found",
"code": "CONFIG_NOTES:DELETE:HISTORY_NOTE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Config Schema
API endpoints for config schema management
Get config schema
requires authentication
Returns list of config schema entries for given firmware version.
Example request:
curl --request GET \
--get "http://localhost:8000/api/versions/firmware/1/schema?filter=modes" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/versions/firmware/1/schema"
);
const params = {
"filter": "modes",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 1,
"firmware_id": 7,
"key": "ratione",
"is_common": 0,
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
},
{
"id": 2,
"firmware_id": 9,
"key": "et",
"is_common": 0,
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view config schema",
"code": "CONFIG_SCHEMA:GET:INSUFFICIENT_PERMISSION"
}
Example response (404, Firmware version not found):
{
"message": "Firmware version not found",
"code": "CONFIG_SCHEMA:GET:FIRMWARE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Add config schema
requires authentication
Add one or many config schema entries. Each entry is one key in config. Body of this request is simple array of objects:
[
{"key": "key_name", "is_common": 1},
{"key": "another_name", "is_common": 0},
...
]
Example request:
curl --request POST \
"http://localhost:8000/api/versions/firmware/minima/schema" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "[
{
\"key\": \"gripsPosition.0.initial\",
\"is_common\": 1
}
]"
const url = new URL(
"http://localhost:8000/api/versions/firmware/minima/schema"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = [
{
"key": "gripsPosition.0.initial",
"is_common": 1
}
];
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
[
{
"id": 3,
"firmware_id": 11,
"key": "molestias",
"is_common": 0,
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
},
{
"id": 4,
"firmware_id": 13,
"key": "ullam",
"is_common": 0,
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage config schema",
"code": "CONFIG_SCHEMA:ADD:INSUFFICIENT_PERMISSION"
}
Example response (404, Firmware version not found):
{
"message": "Firmware version not found",
"code": "CONFIG_SCHEMA:ADD:FIRMWARE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete config schema
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/versions/firmware/1/schema/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/versions/firmware/1/schema/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Config schema entry deleted",
"code": "CONFIG_SCHEMA:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage config schema",
"code": "CONFIG_SCHEMA:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (404, Firmware version not found):
{
"message": "Firmware version not found",
"code": "CONFIG_SCHEMA:DELETE:FIRMWARE_NOT_FOUND"
}
Example response (404, Config schema entry not found):
{
"message": "Config schema entry not found",
"code": "CONFIG_SCHEMA:DELETE:SCHEMA_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Config Templates
API endpoints for managing config templates
Get config templates list
requires authentication
Entries where author is present are private and owned by its author. Entries where author is null should be considered as global templates prepared by Aether team.
Example request:
curl --request GET \
--get "http://localhost:8000/api/config/templates?search=sport&author=1&scope=me" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/config/templates"
);
const params = {
"search": "sport",
"author": "1",
"scope": "me",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"name": "Non aperiam molestiae sint ea dolore.",
"description": "Voluptatibus earum necessitatibus dolores deserunt cupiditate alias.",
"author_id": 96,
"company_id": null,
"config": "{\"autoGrasp\":[1,100],\"coContractionTimings\":[400,100],\"controlMode\":[0],\"emgGains\":[100,100],\"emgSpike\":[1,300],\"emgThresholds\":[40,80,70,0,10,70,20,30,60,20],\"gripPairsConfig\":[6,5,4,10,8,7,11,2],\"gripSequentialConfig\":[3,1,7,2,9,255,255,13,255,255,5,10],\"gripSwitchingMode\":[1],\"holdOpen\":[2500,2500],\"pulseTimings\":[810,100,10,600],\"softGrip\":[1],\"speedControlStrategy\":[1]}",
"created_at": "2026-02-27T12:42:31.000000Z",
"updated_at": "2026-02-27T12:42:31.000000Z",
"author": {
"id": 96,
"mrn": "F4AQI25D1772196151",
"name": "Dr. Breanna Labadie",
"email": "1772196151hegmann.joannie@example.org",
"language": "en",
"phone": "+19855932690",
"phone_country": "KG",
"phone_verified_at": null,
"address1": "7693 Modesto Dam",
"address2": "West Breannefort, MS 47314",
"postal_code": "34652-3316",
"city": "Borer-Hilpert",
"country": "PT",
"clinic_name": "Hudsonfort",
"clinic_location": "60180 Kunze Drive\nNew Rozella, WY 56042",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:31.000000Z",
"updated_at": "2026-02-27T12:42:31.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
},
{
"id": 2,
"name": "Et ipsam velit autem aut quis perspiciatis quos.",
"description": "Assumenda numquam rerum quo et ut qui.",
"author_id": 97,
"company_id": null,
"config": "{\"autoGrasp\":[1,0],\"coContractionTimings\":[400,200],\"controlMode\":[1],\"emgGains\":[100,100],\"emgSpike\":[1,300],\"emgThresholds\":[10,90,100,60,70,40,100,80,40,90],\"gripPairsConfig\":[8,9,1,7,6,10,13,12],\"gripSequentialConfig\":[255,255,255,255,255,1,255,12,255,255,255,6],\"gripSwitchingMode\":[2],\"holdOpen\":[1500,2000],\"pulseTimings\":[500,450,290,200],\"softGrip\":[0],\"speedControlStrategy\":[1]}",
"created_at": "2026-02-27T12:42:31.000000Z",
"updated_at": "2026-02-27T12:42:31.000000Z",
"author": {
"id": 97,
"mrn": "GBATUMEH1772196151",
"name": "Issac Marks I",
"email": "1772196151dare.jade@example.com",
"language": "en",
"phone": "+16788265964",
"phone_country": "MS",
"phone_verified_at": null,
"address1": "118 Mike Mall Suite 051",
"address2": "West Robin, MS 14221-6207",
"postal_code": "39175-1759",
"city": "Turcotte, Harber and Conroy",
"country": "DK",
"clinic_name": "South Marlene",
"clinic_location": "34772 Runte Falls Apt. 137\nBoscohaven, VA 50469-8513",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:31.000000Z",
"updated_at": "2026-02-27T12:42:31.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list config templates",
"code": "CONFIG_TEMPLATES:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get config template
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/config/templates/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/config/templates/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 3,
"name": "Et aut cumque eos pariatur omnis velit.",
"description": "Eos unde magni eaque explicabo veniam unde.",
"author_id": 98,
"company_id": null,
"config": "{\"autoGrasp\":[0,100],\"coContractionTimings\":[200,200],\"controlMode\":[0],\"emgGains\":[100,100],\"emgSpike\":[1,300],\"emgThresholds\":[10,60,30,20,10,90,0,70,0,50],\"gripPairsConfig\":[10,5,4,7,3,6,9,8],\"gripSequentialConfig\":[7,2,4,10,1,255,5,13,3,255,255,6],\"gripSwitchingMode\":[3],\"holdOpen\":[1500,2000],\"pulseTimings\":[210,980,740,860],\"softGrip\":[0],\"speedControlStrategy\":[0]}",
"created_at": "2026-02-27T12:42:31.000000Z",
"updated_at": "2026-02-27T12:42:31.000000Z",
"author": {
"id": 98,
"mrn": "QRGPQLBL1772196151",
"name": "Don King Sr.",
"email": "1772196151chris01@example.com",
"language": "en",
"phone": "816-357-9216",
"phone_country": "PL",
"phone_verified_at": null,
"address1": "61537 Else Crossing",
"address2": "East Laurynbury, WY 83544-2162",
"postal_code": "37887-3931",
"city": "Stehr, Gutkowski and Rath",
"country": "ES",
"clinic_name": "Eldoraview",
"clinic_location": "7261 Pagac Port Apt. 969\nSchowalterland, WY 25825",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:31.000000Z",
"updated_at": "2026-02-27T12:42:31.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view config template",
"code": "CONFIG_TEMPLATES:GET:INSUFFICIENT_PERMISSION"
}
Example response (404, Config template not found):
{
"message": "Config template not found",
"code": "CONFIG_TEMPLATES:GET:TEMPLATE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create new config template
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/config/templates" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Default config for Aether Zeus\",
\"description\": \"Description of the config template.\",
\"owner\": \"company\",
\"author\": 1,
\"config\": \"{\\\"param_1\\\": [100, 200], \\\"param_2\\\": [100, 200, 300]}\"
}"
const url = new URL(
"http://localhost:8000/api/config/templates"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Default config for Aether Zeus",
"description": "Description of the config template.",
"owner": "company",
"author": 1,
"config": "{\"param_1\": [100, 200], \"param_2\": [100, 200, 300]}"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 4,
"name": "Sunt tempore aperiam laudantium ut.",
"description": "Nobis deleniti incidunt aut inventore impedit omnis.",
"author_id": 99,
"company_id": null,
"config": "{\"autoGrasp\":[0,0],\"coContractionTimings\":[300,200],\"controlMode\":[1],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[80,80,40,50,50,50,100,0,30,50],\"gripPairsConfig\":[12,10,9,3,2,8,11,4],\"gripSequentialConfig\":[4,255,6,5,7,255,9,8,12,11,255,255],\"gripSwitchingMode\":[2],\"holdOpen\":[2000,2500],\"pulseTimings\":[60,780,750,800],\"softGrip\":[1],\"speedControlStrategy\":[0]}",
"created_at": "2026-02-27T12:42:31.000000Z",
"updated_at": "2026-02-27T12:42:31.000000Z",
"author": {
"id": 99,
"mrn": "TDRA8XB21772196151",
"name": "May Hayes",
"email": "1772196151thea.hettinger@example.net",
"language": "en",
"phone": "516.575.5506",
"phone_country": "AM",
"phone_verified_at": null,
"address1": "178 Torphy Prairie",
"address2": "Port Addison, WY 77553",
"postal_code": "09845",
"city": "Grimes-Pouros",
"country": "PL",
"clinic_name": "East Easterberg",
"clinic_location": "3881 Linwood Parks\nEricside, UT 63807",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:31.000000Z",
"updated_at": "2026-02-27T12:42:31.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create config template",
"code": "CONFIG_TEMPLATES:CREATE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update config template
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/config/templates/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Default config for Aether Zeus\",
\"description\": \"Description of the config template.\",
\"owner\": \"company\",
\"author\": 1,
\"config\": \"{\\\"param_1\\\": [100, 200], \\\"param_2\\\": [100, 200, 300]}\"
}"
const url = new URL(
"http://localhost:8000/api/config/templates/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Default config for Aether Zeus",
"description": "Description of the config template.",
"owner": "company",
"author": 1,
"config": "{\"param_1\": [100, 200], \"param_2\": [100, 200, 300]}"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 5,
"name": "Quia odio totam mollitia perferendis aspernatur.",
"description": "Occaecati et commodi excepturi.",
"author_id": 100,
"company_id": null,
"config": "{\"autoGrasp\":[1,0],\"coContractionTimings\":[500,400],\"controlMode\":[0],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[40,80,80,40,50,100,100,50,40,40],\"gripPairsConfig\":[13,12,7,11,2,9,8,10],\"gripSequentialConfig\":[10,7,11,13,255,2,6,9,255,5,8,255],\"gripSwitchingMode\":[2],\"holdOpen\":[1500,2000],\"pulseTimings\":[940,340,890,870],\"softGrip\":[1],\"speedControlStrategy\":[0]}",
"created_at": "2026-02-27T12:42:31.000000Z",
"updated_at": "2026-02-27T12:42:31.000000Z",
"author": {
"id": 100,
"mrn": "O6WV70B71772196151",
"name": "Tyreek Jacobi Jr.",
"email": "1772196151rafaela.nicolas@example.com",
"language": "en",
"phone": "+1 (463) 782-1858",
"phone_country": "TW",
"phone_verified_at": null,
"address1": "100 Fadel Motorway",
"address2": "Port Mariah, PA 13723-9241",
"postal_code": "55190",
"city": "Cormier, Daugherty and Ullrich",
"country": "SI",
"clinic_name": "South Sydneyland",
"clinic_location": "5830 Boyle Cape Suite 401\nNew Willis, CO 28483",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:31.000000Z",
"updated_at": "2026-02-27T12:42:31.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update config template",
"code": "CONFIG_TEMPLATES:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Config template not found):
{
"message": "Config template not found",
"code": "CONFIG_TEMPLATES:UPDATE:TEMPLATE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete config template
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/config/templates/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/config/templates/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Config template deleted",
"code": "CONFIG_TEMPLATES:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to delete config template",
"code": "CONFIG_TEMPLATES:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (404, Config template not found):
{
"message": "Config template not found",
"code": "CONFIG_TEMPLATES:DELETE:TEMPLATE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Config Templates Notes
API endpoints for config templates notes
Get config templates notes list
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/config/templates/1/notes?user=1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/config/templates/1/notes"
);
const params = {
"user": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"template_id": 6,
"user_id": 101,
"note": "Inventore est exercitationem blanditiis aliquam totam aspernatur.",
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z",
"author": {
"id": 101,
"mrn": "G7QCAD011772196152",
"name": "Aileen Willms",
"email": "1772196152victoria09@example.net",
"language": "en",
"phone": "+1-228-236-8374",
"phone_country": "MU",
"phone_verified_at": null,
"address1": "43842 Justyn Rest",
"address2": "New Priscillahaven, SC 26001",
"postal_code": "65919-5555",
"city": "Olson Group",
"country": "EE",
"clinic_name": "South Unaport",
"clinic_location": "8949 Kerluke Trail Suite 700\nHildegardfort, NY 39268",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
},
{
"id": 2,
"template_id": 7,
"user_id": 102,
"note": "Cumque voluptas consequatur dolores voluptatum vel.",
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z",
"author": {
"id": 102,
"mrn": "K52PYAP31772196152",
"name": "Leanna Conroy",
"email": "1772196152dprice@example.org",
"language": "en",
"phone": "(971) 882-0632",
"phone_country": "AG",
"phone_verified_at": null,
"address1": "153 Heathcote Highway",
"address2": "O'Connerchester, MI 82735",
"postal_code": "08326-2771",
"city": "Kovacek, Runolfsson and Schiller",
"country": "IT",
"clinic_name": "Jeanstad",
"clinic_location": "4789 Kozey Center\nNew Marjoryfurt, NJ 44396",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to access config templates notes",
"code": "CONFIG_TEMPLATE_NOTES:LIST:INSUFFICIENT_PERMISSION"
}
Example response (404, Config template not found):
{
"message": "Config template not found",
"code": "CONFIG_TEMPLATE_NOTES:LIST:TEMPLATE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get config template note
requires authentication
Returns single config template note in response.
Example request:
curl --request GET \
--get "http://localhost:8000/api/config/templates/1/notes/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/config/templates/1/notes/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 3,
"template_id": 8,
"user_id": 103,
"note": "Maxime voluptatem voluptas repellendus aspernatur nemo explicabo sunt cumque.",
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z",
"author": {
"id": 103,
"mrn": "XN7A41331772196152",
"name": "Ottilie Sauer MD",
"email": "1772196152cole.kiana@example.com",
"language": "en",
"phone": "+1-332-709-2458",
"phone_country": "KW",
"phone_verified_at": null,
"address1": "1072 Moore Path Apt. 177",
"address2": "West Estellefurt, CA 42639-5629",
"postal_code": "93252-1058",
"city": "Veum Ltd",
"country": "SI",
"clinic_name": "Aufderharport",
"clinic_location": "23178 Bernadette Trail Suite 535\nCliffordfort, TN 55334",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to access config templates notes",
"code": "CONFIG_TEMPLATE_NOTES:GET:INSUFFICIENT_PERMISSION"
}
Example response (404, Config template not found):
{
"message": "Config template not found",
"code": "CONFIG_TEMPLATE_NOTES:GET:TEMPLATE_NOT_FOUND"
}
Example response (404, Config template note not found):
{
"message": "Config template note not found",
"code": "CONFIG_TEMPLATE_NOTES:GET:NOTE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create new config template note
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/config/templates/1/notes" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"note\": \"Alias dolorum nobis repellat.\"
}"
const url = new URL(
"http://localhost:8000/api/config/templates/1/notes"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"note": "Alias dolorum nobis repellat."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 4,
"template_id": 9,
"user_id": 104,
"note": "Reiciendis similique ut quo nostrum voluptas et sint.",
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z",
"author": {
"id": 104,
"mrn": "KXNOROT81772196152",
"name": "Darron Hane",
"email": "1772196152albin.vonrueden@example.net",
"language": "en",
"phone": "(205) 356-7813",
"phone_country": "LT",
"phone_verified_at": null,
"address1": "21248 Clementine Stravenue Apt. 182",
"address2": "Greenfeldermouth, MA 70499-7535",
"postal_code": "63604-3334",
"city": "Sanford, Farrell and Ritchie",
"country": "HR",
"clinic_name": "Noemybury",
"clinic_location": "210 Orville Plain\nPort Aimee, IA 61004",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:32.000000Z",
"updated_at": "2026-02-27T12:42:32.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to add config templates notes",
"code": "CONFIG_TEMPLATE_NOTES:CREATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Config template not found):
{
"message": "Config template not found",
"code": "CONFIG_TEMPLATE_NOTES:CREATE:TEMPLATE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete config template note
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/config/templates/1/notes/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/config/templates/1/notes/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Config template note deleted",
"code": "CONFIG_TEMPLATE_NOTES:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to delete config templates notes",
"code": "CONFIG_TEMPLATE_NOTES:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (404, Config template not found):
{
"message": "Config template not found",
"code": "CONFIG_TEMPLATE_NOTES:DELETE:TEMPLATE_NOT_FOUND"
}
Example response (404, Config template note not found):
{
"message": "Config template note not found",
"code": "CONFIG_TEMPLATE_NOTES:DELETE:NOTE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Custom Grips
API endpoints for custom grips management
List custom grips templates
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/custom-grips-templates" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/custom-grips-templates"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"user_id": 255,
"name": "lisandro19",
"initial_position": "[50, 50, 50, 50, 50]",
"limit_position": "[900, 900, 900, 900, 900]",
"active_fingers": "[0, 1, 1, 1, 1]",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
},
{
"id": 2,
"user_id": 256,
"name": "elvie.stokes",
"initial_position": "[50, 50, 50, 50, 50]",
"limit_position": "[900, 900, 900, 900, 900]",
"active_fingers": "[0, 1, 1, 1, 1]",
"created_at": "2026-02-27T12:42:46.000000Z",
"updated_at": "2026-02-27T12:42:46.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage custom grips templates",
"code": "CUSTOM_GRIPS_TEMPLATES:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create custom grip template
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/custom-grips-templates" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Custom Grip Template 1\",
\"initial_position\": \"[50, 50, 50, 50, 50]\",
\"limit_position\": \"[900, 900, 900, 900, 900]\",
\"active_fingers\": \"[0, 1, 1, 1, 1]\"
}"
const url = new URL(
"http://localhost:8000/api/custom-grips-templates"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Custom Grip Template 1",
"initial_position": "[50, 50, 50, 50, 50]",
"limit_position": "[900, 900, 900, 900, 900]",
"active_fingers": "[0, 1, 1, 1, 1]"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 3,
"user_id": 257,
"name": "stevie.pagac",
"initial_position": "[50, 50, 50, 50, 50]",
"limit_position": "[900, 900, 900, 900, 900]",
"active_fingers": "[0, 1, 1, 1, 1]",
"created_at": "2026-02-27T12:42:46.000000Z",
"updated_at": "2026-02-27T12:42:46.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage custom grips templates",
"code": "CUSTOM_GRIPS_TEMPLATES:CREATE:INSUFFICIENT_PERMISSION"
}
Example response (403, Custom grip template name in use):
{
"message": "Custom grip template name already in use",
"code": "CUSTOM_GRIPS_TEMPLATES:CREATE:NAME_IN_USE"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete custom grip template
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/custom-grips-templates/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/custom-grips-templates/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Custom grip deleted",
"code": "CUSTOM_GRIPS_TEMPLATES:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage custom grips templates",
"code": "CUSTOM_GRIPS_TEMPLATES:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (404, Custom grip template not found):
{
"message": "Custom grip template not found",
"code": "CUSTOM_GRIPS_TEMPLATES:DELETE:TEMPLATE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List custom grips
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/device/1/custom-grips" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/custom-grips"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"device_id": 130,
"name": "metz.hank",
"opposed": 1,
"grip_number": 0,
"created_at": "2026-02-27T12:42:46.000000Z",
"updated_at": "2026-02-27T12:42:46.000000Z"
},
{
"id": 2,
"device_id": 131,
"name": "alexis81",
"opposed": 1,
"grip_number": 0,
"created_at": "2026-02-27T12:42:46.000000Z",
"updated_at": "2026-02-27T12:42:46.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view custom grips",
"code": "CUSTOM_GRIPS:LIST:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CUSTOM_GRIPS:LIST:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create custom grip
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/device/1/custom-grips" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Custom Grip 1\",
\"opposed\": true,
\"grip_number\": 1
}"
const url = new URL(
"http://localhost:8000/api/device/1/custom-grips"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Custom Grip 1",
"opposed": true,
"grip_number": 1
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 3,
"device_id": 132,
"name": "brendon.torp",
"opposed": 1,
"grip_number": 0,
"created_at": "2026-02-27T12:42:46.000000Z",
"updated_at": "2026-02-27T12:42:46.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage custom grips",
"code": "CUSTOM_GRIPS:CREATE:INSUFFICIENT_PERMISSION"
}
Example response (403, Custom grip name in use):
{
"message": "Custom grip name already in use",
"code": "CUSTOM_GRIPS:CREATE:NAME_IN_USE"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CUSTOM_GRIPS:CREATE:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update custom grip
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/device/1/custom-grips/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Custom Grip 1\",
\"opposed\": true,
\"grip_number\": 1
}"
const url = new URL(
"http://localhost:8000/api/device/1/custom-grips/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Custom Grip 1",
"opposed": true,
"grip_number": 1
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 4,
"device_id": 133,
"name": "spadberg",
"opposed": 1,
"grip_number": 0,
"created_at": "2026-02-27T12:42:46.000000Z",
"updated_at": "2026-02-27T12:42:46.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage custom grips",
"code": "CUSTOM_GRIPS:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (403, Custom grip name in use):
{
"message": "Custom grip name already in use",
"code": "CUSTOM_GRIPS:UPDATE:NAME_IN_USE"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CUSTOM_GRIPS:UPDATE:DEVICE_NOT_FOUND"
}
Example response (404, Custom grip not found):
{
"message": "Custom grip not found",
"code": "CUSTOM_GRIPS:UPDATE:GRIP_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete custom grip
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/device/1/custom-grips/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/custom-grips/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Custom grip template deleted",
"code": "CUSTOM_GRIPS:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage custom grips",
"code": "CUSTOM_GRIPS:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "CUSTOM_GRIPS:DELETE:DEVICE_NOT_FOUND"
}
Example response (404, Custom grip not found):
{
"message": "Custom grip not found",
"code": "CUSTOM_GRIPS:DELETE:GRIP_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Device Models
API endpoints for device models management
Get device models list
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/devices/models?active=1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/devices/models"
);
const params = {
"active": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 3,
"name": "Zeus hand v1",
"type": "arm",
"orientation": "right",
"active": 1,
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z"
},
{
"id": 4,
"name": "Zeus hand v1",
"type": "arm",
"orientation": "left",
"active": 1,
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list device models",
"code": "DEVICE_MODELS:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create device model
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/devices/models" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Zeus hand v1\",
\"type\": \"hand\",
\"orientation\": \"right\",
\"active\": true
}"
const url = new URL(
"http://localhost:8000/api/devices/models"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Zeus hand v1",
"type": "hand",
"orientation": "right",
"active": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 5,
"name": "Zeus hand v1",
"type": "leg",
"orientation": "left",
"active": 1,
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create device model",
"code": "DEVICE_MODELS:CREATE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update device model
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/devices/models/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Zeus hand v1\",
\"type\": \"hand\",
\"orientation\": \"right\",
\"active\": true
}"
const url = new URL(
"http://localhost:8000/api/devices/models/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Zeus hand v1",
"type": "hand",
"orientation": "right",
"active": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 6,
"name": "Zeus hand v1",
"type": "leg",
"orientation": "left",
"active": 1,
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update device model",
"code": "DEVICE_MODELS:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Device model not found):
{
"message": "Device model not found",
"code": "DEVICE_MODELS:UPDATE:MODEL_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Devices
API endpoints for devices management
Check serial number or bluetooth ID
Public endpoint responding with status of given device serial number or bluetooth ID. If any of these numbers can be found in database, status will be true. Otherwise, status will be false (device does not exist).
Example request:
curl --request GET \
--get "http://localhost:8000/api/device/check/S3R1AL-NUM83R" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"type\": \"serial\"
}"
const url = new URL(
"http://localhost:8000/api/device/check/S3R1AL-NUM83R"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"type": "serial"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"status": true
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get devices list
requires authentication
Possible extend options:
- model - device model details
- amputee - end-user assigned to device
- clinicians - list of clinicians assigned to the device
- firmwareVersion - device firmware version
- pcbVersion - PCB version
Example request:
curl --request GET \
--get "http://localhost:8000/api/devices?search=S3R1AL-NUM83R&active=-1&utee=1&clinician=1&model=1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/devices"
);
const params = {
"search": "S3R1AL-NUM83R",
"active": "-1",
"amputee": "1",
"clinician": "1",
"model": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 5,
"serial": "0cc68e93-c473-3af4-bbd8-18e670cad887",
"bluetooth_id": "3ae5cec8-1fa5-3728-a6ce-628b248f8a25",
"company_id": null,
"model_id": 7,
"amputee_id": 34,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z",
"model": {
"id": 7,
"name": "Zeus hand v1",
"type": "leg",
"orientation": "left",
"active": 1,
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z"
},
"amputee": {
"id": 34,
"mrn": "WAM0H62C1772196145",
"name": "Delores Lockman",
"email": "1772196145joey29@example.com",
"language": "en",
"phone": "+1-830-293-9188",
"phone_country": "BA",
"phone_verified_at": null,
"address1": "244 Cathrine Track Suite 031",
"address2": "Port Danikamouth, NM 71969-1571",
"postal_code": "30669-0125",
"city": "Bechtelar, Considine and Emard",
"country": "AT",
"clinic_name": "Port Cameronstad",
"clinic_location": "59629 Morton Walks\nGiovanishire, CA 87766",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
},
{
"id": 6,
"serial": "eda850ff-6589-3155-90ad-794d7738c812",
"bluetooth_id": "6506fbd4-6132-3036-9a99-c904b19684db",
"company_id": null,
"model_id": 8,
"amputee_id": 35,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z",
"model": {
"id": 8,
"name": "Zeus hand v1",
"type": "leg",
"orientation": "left",
"active": 1,
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z"
},
"amputee": {
"id": 35,
"mrn": "XPGMD0JB1772196145",
"name": "Prof. Marlon Fadel",
"email": "1772196145batz.estrella@example.com",
"language": "en",
"phone": "(925) 568-4577",
"phone_country": "LB",
"phone_verified_at": null,
"address1": "491 Green Isle",
"address2": "Reggieville, FL 98166-8353",
"postal_code": "40977",
"city": "Lubowitz-Klein",
"country": "GR",
"clinic_name": "Lake Merlinborough",
"clinic_location": "57369 Kara Orchard Apt. 595\nMurphyfurt, CT 46400",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list devices",
"code": "DEVICES:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get device information
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/device/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 7,
"serial": "d4be7e92-53c6-349c-8381-c718cd35c00d",
"bluetooth_id": "5e22a4ad-ff7c-3e7f-b6f4-e6322bca7dd1",
"company_id": null,
"model_id": 9,
"amputee_id": 36,
"clinician_id": null,
"firmware_version_id": 1,
"pcb_version_id": 1,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z",
"model": {
"id": 9,
"name": "Zeus hand v1",
"type": "arm",
"orientation": "right",
"active": 1,
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z"
},
"amputee": {
"id": 36,
"mrn": "MME9K7U91772196145",
"name": "Alisa Wolff",
"email": "1772196145meredith11@example.com",
"language": "en",
"phone": "754-740-6462",
"phone_country": "UA",
"phone_verified_at": null,
"address1": "2864 Jacobs Garden",
"address2": "East Arlo, KY 48907",
"postal_code": "58183-0331",
"city": "Spencer-Sporer",
"country": "HU",
"clinic_name": "Abshireshire",
"clinic_location": "7517 Griffin Lock Apt. 247\nKochview, GA 00123",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"pcb_version": {
"id": 1,
"name": "7.94.66",
"hardware_id": "",
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z"
}
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view device data",
"code": "DEVICES:GET:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "DEVICES:GET:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create new device
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/device" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"serial\": \"S3R1AL-NUM83R\",
\"bluetooth_id\": \"BL0123456789\",
\"model_id\": 1,
\"amputee_id\": 1,
\"clinicians\": [
2
],
\"firmware_version_id\": 1,
\"pcb_version_id\": 1,
\"reverse_magnets\": false,
\"is_electrode\": false,
\"active\": true,
\"last_activity_at\": \"2022-08-15 12:00:00\"
}"
const url = new URL(
"http://localhost:8000/api/device"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"serial": "S3R1AL-NUM83R",
"bluetooth_id": "BL0123456789",
"model_id": 1,
"amputee_id": 1,
"clinicians": [
2
],
"firmware_version_id": 1,
"pcb_version_id": 1,
"reverse_magnets": false,
"is_electrode": false,
"active": true,
"last_activity_at": "2022-08-15 12:00:00"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 8,
"serial": "6c55ca63-671c-3bc4-9103-09c5dd93874e",
"bluetooth_id": "fc697788-85d9-34bd-9c7d-5f63c950de11",
"company_id": null,
"model_id": null,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create device",
"code": "DEVICES:CREATE:INSUFFICIENT_PERMISSION"
}
Example response (403, Firmware has no schema):
{
"message": "Cannot create: firmware has no schema",
"code": "DEVICES:CREATE:NO_FIRMWARE_SCHEMA"
}
Example response (500, Server error):
{
"message": "Server error: device not created",
"code": "DEVICES:CREATE:SERVER_ERROR"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update device
requires authentication
Amputee of device can update only these fields:
serial, bluetooth_id, firmware_version_id, pcb_version_id
Example request:
curl --request PUT \
"http://localhost:8000/api/device/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"serial\": \"S3R1AL-NUM83R\",
\"bluetooth_id\": \"BL0123456789\",
\"model_id\": 1,
\"amputee_id\": 1,
\"clinicians\": [
2
],
\"firmware_version_id\": 1,
\"pcb_version_id\": 1,
\"reverse_magnets\": false,
\"is_electrode\": false,
\"active\": true,
\"last_activity_at\": \"2022-08-15 12:00:00\"
}"
const url = new URL(
"http://localhost:8000/api/device/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"serial": "S3R1AL-NUM83R",
"bluetooth_id": "BL0123456789",
"model_id": 1,
"amputee_id": 1,
"clinicians": [
2
],
"firmware_version_id": 1,
"pcb_version_id": 1,
"reverse_magnets": false,
"is_electrode": false,
"active": true,
"last_activity_at": "2022-08-15 12:00:00"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 9,
"serial": "a2e15ca2-2577-31a7-b6d3-dc0aa77906e7",
"bluetooth_id": "3f3d8ef2-f3ea-3fd1-878f-0360bb73fc65",
"company_id": null,
"model_id": null,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update device",
"code": "DEVICES:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (403, Firmware has no schema):
{
"message": "Cannot update: firmware has no schema",
"code": "DEVICES:UPDATE:NO_FIRMWARE_SCHEMA"
}
Example response (403):
{
"message": "Cannot update: no clinicians left for patient relation",
"code": "DEVICES:UPDATE:NO_CLINICIANS"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "DEVICES:UPDATE:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete device
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/device/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Device deleted",
"code": "DEVICES:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to delete device",
"code": "DEVICES:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "DEVICES:DELETE:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get device hashes
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/device/1/hash" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/hash"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"hash_global": "123456789012345",
"hash_common_settings": "123456789012345",
"hash_common_grips": "123456789012345",
"hash_mode1": "123456789012345",
"hash_mode2": "123456789012345",
"hash_mode3": "123456789012345"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to access device hashes",
"code": "DEVICES:GET_HASHES:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "DEVICES:GET_HASHES:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update device hashes
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/device/1/hash" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"hash_global\": \"123456789012345\",
\"hash_common_settings\": \"123456789012345\",
\"hash_common_grips\": \"123456789012345\",
\"hash_mode1\": \"123456789012345\",
\"hash_mode2\": \"123456789012345\",
\"hash_mode3\": \"123456789012345\"
}"
const url = new URL(
"http://localhost:8000/api/device/1/hash"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"hash_global": "123456789012345",
"hash_common_settings": "123456789012345",
"hash_common_grips": "123456789012345",
"hash_mode1": "123456789012345",
"hash_mode2": "123456789012345",
"hash_mode3": "123456789012345"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202, OK):
{
"hash_global": "123456789012345",
"hash_common_settings": "123456789012345",
"hash_common_grips": "123456789012345",
"hash_mode1": "123456789012345",
"hash_mode2": "123456789012345",
"hash_mode3": "123456789012345"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to access device hashes",
"code": "DEVICES:SET_HASHES:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "DEVICES:SET_HASHES:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Detach device
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/device/1/detach" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/detach"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Device detached",
"code": "DEVICES:DETACH:DETACHED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to detach device",
"code": "DEVICES:DETACH:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "DEVICES:DETACH:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Add device
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/device/add/S3R1AL-NUM83R" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/add/S3R1AL-NUM83R"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (202):
{
"id": 10,
"serial": "2060a40a-aa39-314e-896e-a2b69d27bd59",
"bluetooth_id": "b7bfa3fc-b74e-3bc9-bfc9-0c3bdd0fe390",
"company_id": null,
"model_id": null,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to assign devices with code",
"code": "DEVICES:ASSIGN:INSUFFICIENT_PERMISSION"
}
Example response (403, User reached the temporary limit of attached devices):
{
"message": "Reached the limit of assigned devices",
"code": "DEVICES:ASSIGN:LIMIT_REACHED"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "DEVICES:ASSIGN:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Connect device
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/device/connect/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/connect/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200, OK):
{
"message": "Device connected",
"code": "DEVICES:CONNECT:CONNECTED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view device data",
"code": "DEVICES:CONNECT:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "DEVICES:CONNECT:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Disconnect device
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/device/disconnect/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/disconnect/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200, OK):
{
"message": "Device disconnected",
"code": "DEVICES:DISCONNECT:DISCONNECTED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view device data",
"code": "DEVICES:DISCONNECT:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "DEVICES:DISCONNECT:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Join devices
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/device/join/1/2" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"force\": false,
\"patient\": 1
}"
const url = new URL(
"http://localhost:8000/api/device/join/1/2"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"force": false,
"patient": 1
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"id": 11,
"serial": "034b55aa-f9c5-399d-aeb3-eb9fefbc2e98",
"bluetooth_id": "51754b92-ba2b-3a5a-bb56-b0fa65a17c53",
"company_id": null,
"model_id": null,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z",
"joined_devices": [
{
"id": 12,
"serial": "a6994ba8-5da5-37e6-9950-b050b5c19598",
"bluetooth_id": "87076957-dd38-3f73-b517-198b9b3a16e9",
"company_id": null,
"model_id": null,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z",
"pivot": {
"electrode_id": 11,
"device_id": 12,
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z"
}
}
],
"joined_electrodes": [
{
"id": 13,
"serial": "1e1e5c7e-b4bd-3ed3-b038-6dffbbe9bb67",
"bluetooth_id": "c20c3015-fac7-313f-a21f-9530e1970bf3",
"company_id": null,
"model_id": null,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z",
"pivot": {
"device_id": 11,
"electrode_id": 13,
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z"
}
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to join devices",
"code": "DEVICES:JOIN:INSUFFICIENT_PERMISSION"
}
Example response (403, Device already has an electrode joined):
{
"message": "Device already has an electrode joined",
"code": "DEVICES:JOIN:ALREADY_JOINED"
}
Example response (403, Server error):
{
"message": "Server error",
"code": "DEVICES:JOIN:SERVER_ERROR"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "DEVICES:JOIN:DEVICE_NOT_FOUND"
}
Example response (404, Device 1 cannot be an electrode):
{
"message": "Device 1 cannot be an electrode",
"code": "DEVICES:JOIN:INCORRECT_DEVICE1_TYPE"
}
Example response (404, Device 2 must be an electrode):
{
"message": "Device 1 must be an electrode",
"code": "DEVICES:JOIN:INCORRECT_DEVICE2_TYPE"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Detach joined devices
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/device/unjoin/1/2" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/unjoin/1/2"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200, OK):
{
"message": "Devices unjoined",
"code": "DEVICES:UNJOIN:UNJOINED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to join devices",
"code": "DEVICES:UNJOIN:INSUFFICIENT_PERMISSION"
}
Example response (403, OK):
{
"message": "Devices are not joined",
"code": "DEVICES:UNJOIN:NOT_JOINED"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "DEVICES:UNJOIN:DEVICE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create demo patient
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/device/1/dummy-patient" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/device/1/dummy-patient"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (201, OK):
{
"email": "SERIAL@gmail.com",
"password": "Demo@123"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create dummy patient",
"code": "DEVICES:DUMMY_PATIENT:INSUFFICIENT_PERMISSION"
}
Example response (403, Device already has a patient):
{
"message": "Device already has a patient",
"code": "DEVICES:DUMMY_PATIENT:PATIENT_EXISTS"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "DEVICES:DUMMY_PATIENT:DEVICE_NOT_FOUND"
}
Example response (500, Server error):
{
"message": "Server error: dummy patient not created",
"code": "DEVICES:DUMMY_PATIENT:SERVER_ERROR"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Documents
API endpoints for documents management
List documents
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/documents?type=web" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/documents"
);
const params = {
"type": "web",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"name": "Grips",
"type": "mobile",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
},
{
"id": 2,
"name": "Social Work Teacher",
"type": "mobile",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage documents",
"code": "DOCUMENTS:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create document
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/documents" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Privacy Policy\",
\"type\": \"web\"
}"
const url = new URL(
"http://localhost:8000/api/documents"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Privacy Policy",
"type": "web"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 3,
"name": "Construction Carpenter",
"type": "web",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage documents",
"code": "DOCUMENTS:CREATE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete document
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/documents/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/documents/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Document deleted",
"code": "DOCUMENTS:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage documents",
"code": "DOCUMENTS:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (403, Document has existing versions):
{
"message": "Cannot delete: document has existing versions (1)",
"code": "DOCUMENTS:DELETE:HAS_VERSIONS"
}
Example response (404, Document not found):
{
"message": "Document not found",
"code": "DOCUMENTS:DELETE:DOCUMENT_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List document versions
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/documents/1/versions" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/documents/1/versions"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 1,
"document_id": null,
"index": 330560,
"file": "http://breitenberg.com/",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
},
{
"id": 2,
"document_id": null,
"index": 2572,
"file": "http://stracke.com/earum-vel-voluptatibus-quas-aut-expedita-ea",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage documents",
"code": "DOCUMENTS:LIST_VERSIONS:INSUFFICIENT_PERMISSION"
}
Example response (404, Document not found):
{
"message": "Document not found",
"code": "DOCUMENTS:LIST_VERSIONS:DOCUMENT_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create document version
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/documents/1/versions" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"file\": \"https:\\/\\/www.aetherbiomedical.com\\/privacy-policy\"
}"
const url = new URL(
"http://localhost:8000/api/documents/1/versions"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"file": "https:\/\/www.aetherbiomedical.com\/privacy-policy"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 3,
"document_id": null,
"index": 6948288,
"file": "http://www.bashirian.com/provident-est-enim-est",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage documents",
"code": "DOCUMENTS:CREATE_VERSION:INSUFFICIENT_PERMISSION"
}
Example response (404, Document not found):
{
"message": "Document not found",
"code": "DOCUMENTS:CREATE_VERSION:DOCUMENT_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete document version
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/documents/1/versions/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/documents/1/versions/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Document version deleted",
"code": "DOCUMENTS:DELETE_VERSION:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage documents",
"code": "DOCUMENTS:DELETE_VERSION:INSUFFICIENT_PERMISSION"
}
Example response (404, Document not found):
{
"message": "Document not found",
"code": "DOCUMENTS:DELETE_VERSION:DOCUMENT_NOT_FOUND"
}
Example response (404, Document version not found):
{
"message": "Document version not found",
"code": "DOCUMENTS:DELETE_VERSION:VERSION_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get documents status
requires authentication
Any document on the list has to be accepted. Use POST /documents/accept endpoint to mark them as accepted once user agrees to that.
Empty list means that user is up-to-date with all required documents and nothing has to be accepted.
Example request:
curl --request GET \
--get "http://localhost:8000/api/documents/status?type=web" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/documents/status"
);
const params = {
"type": "web",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"documents": [],
"texts": {
"title": "Changes to the Privacy Policy",
"description": "Due to the addition of a new data processing entity, please familiarize yourself with and accept the new privacy policy",
"checkbox": "I declare that I have read the content of the Privacy Policy and the Terms and Conditions and accept their provisions. I understand that acceptance is a condition for using the application."
}
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view documents status",
"code": "DOCUMENTS:STATUS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Accept documents
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/documents/accept" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"documents\": [
1
]
}"
const url = new URL(
"http://localhost:8000/api/documents/accept"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"documents": [
1
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202, OK):
{
"message": "Accepted 1 document(s)",
"code": "DOCUMENTS:ACCEPT:ACCEPTED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update documents status",
"code": "DOCUMENTS:ACCEPT:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Feedback
Endpoints related to feedback collecting
Check feedback token
Example request:
curl --request POST \
"http://localhost:8000/api/feedback/4KJ2YLM0MA64Y6D6FUY2OFY690IICO1OJ2DHR6T68IZNI528H3SKUFJMY0C5DHOA/check" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/feedback/4KJ2YLM0MA64Y6D6FUY2OFY690IICO1OJ2DHR6T68IZNI528H3SKUFJMY0C5DHOA/check"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200, OK):
{
"valid": true
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Send feedback with token
Example request:
curl --request POST \
"http://localhost:8000/api/feedback/4KJ2YLM0MA64Y6D6FUY2OFY690IICO1OJ2DHR6T68IZNI528H3SKUFJMY0C5DHOA" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"rate\": 5,
\"description\": \"That was amazing!\",
\"skipped\": false,
\"training_day_id\": 1
}"
const url = new URL(
"http://localhost:8000/api/feedback/4KJ2YLM0MA64Y6D6FUY2OFY690IICO1OJ2DHR6T68IZNI528H3SKUFJMY0C5DHOA"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"rate": 5,
"description": "That was amazing!",
"skipped": false,
"training_day_id": 1
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 1,
"user_id": 6,
"type": "on_demand",
"trigger": "grip_change",
"platform": "mobile",
"rate": 2,
"description": "Eos in doloribus est voluptatum quo enim omnis.",
"skipped": 1,
"training_day_id": null,
"created_at": "2026-02-27T12:42:22.000000Z",
"updated_at": "2026-02-27T12:42:22.000000Z"
}
Example response (403, Invalid token):
{
"message": "Invalid token",
"code": "FEEDBACK:SEND_WITH_TOKEN:INVALID_TOKEN"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get feedback status
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/feedback/status" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/feedback/status"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"remote_session": true,
"firmware_update": true,
"local_session": true,
"async_session": true,
"patient_create": false,
"clinician_invite": true
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to check feedback status",
"code": "FEEDBACK:STATUS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Send feedback
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/feedback" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"type\": \"contextual\",
\"trigger\": \"remote_session\",
\"platform\": \"web\",
\"rate\": 5,
\"description\": \"That was amazing!\",
\"skipped\": false,
\"training_day_id\": 1
}"
const url = new URL(
"http://localhost:8000/api/feedback"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"type": "contextual",
"trigger": "remote_session",
"platform": "web",
"rate": 5,
"description": "That was amazing!",
"skipped": false,
"training_day_id": 1
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 2,
"user_id": 306,
"type": "periodic",
"trigger": "async_session",
"platform": "mobile",
"rate": 1,
"description": "Et accusantium voluptas voluptatem labore incidunt id et.",
"skipped": 1,
"training_day_id": null,
"created_at": "2026-02-27T12:42:50.000000Z",
"updated_at": "2026-02-27T12:42:50.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to send feedback",
"code": "FEEDBACK:SEND:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List feedback
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/feedback" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/feedback"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (201):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 25,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 3,
"user_id": 307,
"type": "contextual",
"trigger": "remote_session",
"platform": "mobile",
"rate": 3,
"description": "A sunt omnis eos voluptatem aut ab dolor et.",
"skipped": 1,
"training_day_id": null,
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z"
},
{
"id": 4,
"user_id": 308,
"type": "on_demand",
"trigger": "firmware_update",
"platform": "web",
"rate": 2,
"description": "Exercitationem non doloribus nulla distinctio nam.",
"skipped": 1,
"training_day_id": null,
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list feedback",
"code": "FEEDBACK:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Export feedback to CSV
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/feedback/csv" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/feedback/csv"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, CSV file):
{
"file": "https://staging-us-east-2-aether-biomedical-s3-us-bucket.s3.us-east-2.amazonaws.com/feedback/feedback-1759228216.csv",
"expires": "2025-09-30 10:40:00"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to export feedback",
"code": "FEEDBACK:EXPORT_CSV:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get feedback cooldowns
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/feedback/cooldowns" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/feedback/cooldowns"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"remote_session": 1,
"local_session": 1,
"async_session": 1,
"patient_create": 1,
"clinician_invite": 1,
"firmware_update": 1,
"new_config": 1,
"grip_change": 1
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage feedback cooldowns",
"code": "FEEDBACK:GET_COOLDOWNS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update feedback cooldowns
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/feedback/cooldowns" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"remote_session\": 1,
\"local_session\": 1,
\"async_session\": 1,
\"patient_create\": 1,
\"clinician_invite\": 1,
\"firmware_update\": 1,
\"new_config\": 1,
\"grip_change\": 1
}"
const url = new URL(
"http://localhost:8000/api/feedback/cooldowns"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"remote_session": 1,
"local_session": 1,
"async_session": 1,
"patient_create": 1,
"clinician_invite": 1,
"firmware_update": 1,
"new_config": 1,
"grip_change": 1
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"remote_session": 1,
"local_session": 1,
"async_session": 1,
"patient_create": 1,
"clinician_invite": 1,
"firmware_update": 1,
"new_config": 1,
"grip_change": 1
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage feedback cooldowns",
"code": "FEEDBACK:UPDATE_COOLDOWNS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
GeoData
API endpoints for geodata
Get supported timezones list
Example request:
curl --request GET \
--get "http://localhost:8000/api/timezones" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/timezones"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
[
"Africa/Abidjan",
"Africa/Accra",
"Africa/Addis_Ababa",
"Africa/Algiers",
"Africa/Asmara",
"Africa/Bamako",
"Africa/Bangui",
"Africa/Banjul",
"Africa/Bissau",
"Africa/Blantyre",
"Africa/Brazzaville",
"Africa/Bujumbura",
"Africa/Cairo",
"Africa/Casablanca",
"Africa/Ceuta",
"Africa/Conakry",
"Africa/Dakar",
"Africa/Dar_es_Salaam",
"Africa/Djibouti",
"Africa/Douala",
"Africa/El_Aaiun",
"Africa/Freetown",
"Africa/Gaborone",
"Africa/Harare",
"Africa/Johannesburg",
"Africa/Juba",
"Africa/Kampala",
"Africa/Khartoum",
"Africa/Kigali",
"Africa/Kinshasa",
"Africa/Lagos",
"Africa/Libreville",
"Africa/Lome",
"Africa/Luanda",
"Africa/Lubumbashi",
"Africa/Lusaka",
"Africa/Malabo",
"Africa/Maputo",
"Africa/Maseru",
"Africa/Mbabane",
"Africa/Mogadishu",
"Africa/Monrovia",
"Africa/Nairobi",
"Africa/Ndjamena",
"Africa/Niamey",
"Africa/Nouakchott",
"Africa/Ouagadougou",
"Africa/Porto-Novo",
"Africa/Sao_Tome",
"Africa/Tripoli",
"Africa/Tunis",
"Africa/Windhoek",
"America/Adak",
"America/Anchorage",
"America/Anguilla",
"America/Antigua",
"America/Araguaina",
"America/Argentina/Buenos_Aires",
"America/Argentina/Catamarca",
"America/Argentina/Cordoba",
"America/Argentina/Jujuy",
"America/Argentina/La_Rioja",
"America/Argentina/Mendoza",
"America/Argentina/Rio_Gallegos",
"America/Argentina/Salta",
"America/Argentina/San_Juan",
"America/Argentina/San_Luis",
"America/Argentina/Tucuman",
"America/Argentina/Ushuaia",
"America/Aruba",
"America/Asuncion",
"America/Atikokan",
"America/Bahia",
"America/Bahia_Banderas",
"America/Barbados",
"America/Belem",
"America/Belize",
"America/Blanc-Sablon",
"America/Boa_Vista",
"America/Bogota",
"America/Boise",
"America/Cambridge_Bay",
"America/Campo_Grande",
"America/Cancun",
"America/Caracas",
"America/Cayenne",
"America/Cayman",
"America/Chicago",
"America/Chihuahua",
"America/Costa_Rica",
"America/Creston",
"America/Cuiaba",
"America/Curacao",
"America/Danmarkshavn",
"America/Dawson",
"America/Dawson_Creek",
"America/Denver",
"America/Detroit",
"America/Dominica",
"America/Edmonton",
"America/Eirunepe",
"America/El_Salvador",
"America/Fort_Nelson",
"America/Fortaleza",
"America/Glace_Bay",
"America/Goose_Bay",
"America/Grand_Turk",
"America/Grenada",
"America/Guadeloupe",
"America/Guatemala",
"America/Guayaquil",
"America/Guyana",
"America/Halifax",
"America/Havana",
"America/Hermosillo",
"America/Indiana/Indianapolis",
"America/Indiana/Knox",
"America/Indiana/Marengo",
"America/Indiana/Petersburg",
"America/Indiana/Tell_City",
"America/Indiana/Vevay",
"America/Indiana/Vincennes",
"America/Indiana/Winamac",
"America/Inuvik",
"America/Iqaluit",
"America/Jamaica",
"America/Juneau",
"America/Kentucky/Louisville",
"America/Kentucky/Monticello",
"America/Kralendijk",
"America/La_Paz",
"America/Lima",
"America/Los_Angeles",
"America/Lower_Princes",
"America/Maceio",
"America/Managua",
"America/Manaus",
"America/Marigot",
"America/Martinique",
"America/Matamoros",
"America/Mazatlan",
"America/Menominee",
"America/Merida",
"America/Metlakatla",
"America/Mexico_City",
"America/Miquelon",
"America/Moncton",
"America/Monterrey",
"America/Montevideo",
"America/Montserrat",
"America/Nassau",
"America/New_York",
"America/Nipigon",
"America/Nome",
"America/Noronha",
"America/North_Dakota/Beulah",
"America/North_Dakota/Center",
"America/North_Dakota/New_Salem",
"America/Nuuk",
"America/Ojinaga",
"America/Panama",
"America/Pangnirtung",
"America/Paramaribo",
"America/Phoenix",
"America/Port-au-Prince",
"America/Port_of_Spain",
"America/Porto_Velho",
"America/Puerto_Rico",
"America/Punta_Arenas",
"America/Rainy_River",
"America/Rankin_Inlet",
"America/Recife",
"America/Regina",
"America/Resolute",
"America/Rio_Branco",
"America/Santarem",
"America/Santiago",
"America/Santo_Domingo",
"America/Sao_Paulo",
"America/Scoresbysund",
"America/Sitka",
"America/St_Barthelemy",
"America/St_Johns",
"America/St_Kitts",
"America/St_Lucia",
"America/St_Thomas",
"America/St_Vincent",
"America/Swift_Current",
"America/Tegucigalpa",
"America/Thule",
"America/Thunder_Bay",
"America/Tijuana",
"America/Toronto",
"America/Tortola",
"America/Vancouver",
"America/Whitehorse",
"America/Winnipeg",
"America/Yakutat",
"America/Yellowknife",
"Antarctica/Casey",
"Antarctica/Davis",
"Antarctica/DumontDUrville",
"Antarctica/Macquarie",
"Antarctica/Mawson",
"Antarctica/McMurdo",
"Antarctica/Palmer",
"Antarctica/Rothera",
"Antarctica/Syowa",
"Antarctica/Troll",
"Antarctica/Vostok",
"Arctic/Longyearbyen",
"Asia/Aden",
"Asia/Almaty",
"Asia/Amman",
"Asia/Anadyr",
"Asia/Aqtau",
"Asia/Aqtobe",
"Asia/Ashgabat",
"Asia/Atyrau",
"Asia/Baghdad",
"Asia/Bahrain",
"Asia/Baku",
"Asia/Bangkok",
"Asia/Barnaul",
"Asia/Beirut",
"Asia/Bishkek",
"Asia/Brunei",
"Asia/Chita",
"Asia/Choibalsan",
"Asia/Colombo",
"Asia/Damascus",
"Asia/Dhaka",
"Asia/Dili",
"Asia/Dubai",
"Asia/Dushanbe",
"Asia/Famagusta",
"Asia/Gaza",
"Asia/Hebron",
"Asia/Ho_Chi_Minh",
"Asia/Hong_Kong",
"Asia/Hovd",
"Asia/Irkutsk",
"Asia/Jakarta",
"Asia/Jayapura",
"Asia/Jerusalem",
"Asia/Kabul",
"Asia/Kamchatka",
"Asia/Karachi",
"Asia/Kathmandu",
"Asia/Khandyga",
"Asia/Kolkata",
"Asia/Krasnoyarsk",
"Asia/Kuala_Lumpur",
"Asia/Kuching",
"Asia/Kuwait",
"Asia/Macau",
"Asia/Magadan",
"Asia/Makassar",
"Asia/Manila",
"Asia/Muscat",
"Asia/Nicosia",
"Asia/Novokuznetsk",
"Asia/Novosibirsk",
"Asia/Omsk",
"Asia/Oral",
"Asia/Phnom_Penh",
"Asia/Pontianak",
"Asia/Pyongyang",
"Asia/Qatar",
"Asia/Qostanay",
"Asia/Qyzylorda",
"Asia/Riyadh",
"Asia/Sakhalin",
"Asia/Samarkand",
"Asia/Seoul",
"Asia/Shanghai",
"Asia/Singapore",
"Asia/Srednekolymsk",
"Asia/Taipei",
"Asia/Tashkent",
"Asia/Tbilisi",
"Asia/Tehran",
"Asia/Thimphu",
"Asia/Tokyo",
"Asia/Tomsk",
"Asia/Ulaanbaatar",
"Asia/Urumqi",
"Asia/Ust-Nera",
"Asia/Vientiane",
"Asia/Vladivostok",
"Asia/Yakutsk",
"Asia/Yangon",
"Asia/Yekaterinburg",
"Asia/Yerevan",
"Atlantic/Azores",
"Atlantic/Bermuda",
"Atlantic/Canary",
"Atlantic/Cape_Verde",
"Atlantic/Faroe",
"Atlantic/Madeira",
"Atlantic/Reykjavik",
"Atlantic/South_Georgia",
"Atlantic/St_Helena",
"Atlantic/Stanley",
"Australia/Adelaide",
"Australia/Brisbane",
"Australia/Broken_Hill",
"Australia/Darwin",
"Australia/Eucla",
"Australia/Hobart",
"Australia/Lindeman",
"Australia/Lord_Howe",
"Australia/Melbourne",
"Australia/Perth",
"Australia/Sydney",
"Europe/Amsterdam",
"Europe/Andorra",
"Europe/Astrakhan",
"Europe/Athens",
"Europe/Belgrade",
"Europe/Berlin",
"Europe/Bratislava",
"Europe/Brussels",
"Europe/Bucharest",
"Europe/Budapest",
"Europe/Busingen",
"Europe/Chisinau",
"Europe/Copenhagen",
"Europe/Dublin",
"Europe/Gibraltar",
"Europe/Guernsey",
"Europe/Helsinki",
"Europe/Isle_of_Man",
"Europe/Istanbul",
"Europe/Jersey",
"Europe/Kaliningrad",
"Europe/Kiev",
"Europe/Kirov",
"Europe/Lisbon",
"Europe/Ljubljana",
"Europe/London",
"Europe/Luxembourg",
"Europe/Madrid",
"Europe/Malta",
"Europe/Mariehamn",
"Europe/Minsk",
"Europe/Monaco",
"Europe/Moscow",
"Europe/Oslo",
"Europe/Paris",
"Europe/Podgorica",
"Europe/Prague",
"Europe/Riga",
"Europe/Rome",
"Europe/Samara",
"Europe/San_Marino",
"Europe/Sarajevo",
"Europe/Saratov",
"Europe/Simferopol",
"Europe/Skopje",
"Europe/Sofia",
"Europe/Stockholm",
"Europe/Tallinn",
"Europe/Tirane",
"Europe/Ulyanovsk",
"Europe/Uzhgorod",
"Europe/Vaduz",
"Europe/Vatican",
"Europe/Vienna",
"Europe/Vilnius",
"Europe/Volgograd",
"Europe/Warsaw",
"Europe/Zagreb",
"Europe/Zaporozhye",
"Europe/Zurich",
"Indian/Antananarivo",
"Indian/Chagos",
"Indian/Christmas",
"Indian/Cocos",
"Indian/Comoro",
"Indian/Kerguelen",
"Indian/Mahe",
"Indian/Maldives",
"Indian/Mauritius",
"Indian/Mayotte",
"Indian/Reunion",
"Pacific/Apia",
"Pacific/Auckland",
"Pacific/Bougainville",
"Pacific/Chatham",
"Pacific/Chuuk",
"Pacific/Easter",
"Pacific/Efate",
"Pacific/Fakaofo",
"Pacific/Fiji",
"Pacific/Funafuti",
"Pacific/Galapagos",
"Pacific/Gambier",
"Pacific/Guadalcanal",
"Pacific/Guam",
"Pacific/Honolulu",
"Pacific/Kanton",
"Pacific/Kiritimati",
"Pacific/Kosrae",
"Pacific/Kwajalein",
"Pacific/Majuro",
"Pacific/Marquesas",
"Pacific/Midway",
"Pacific/Nauru",
"Pacific/Niue",
"Pacific/Norfolk",
"Pacific/Noumea",
"Pacific/Pago_Pago",
"Pacific/Palau",
"Pacific/Pitcairn",
"Pacific/Pohnpei",
"Pacific/Port_Moresby",
"Pacific/Rarotonga",
"Pacific/Saipan",
"Pacific/Tahiti",
"Pacific/Tarawa",
"Pacific/Tongatapu",
"Pacific/Wake",
"Pacific/Wallis",
"UTC"
]
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Goals
API endpoints for goals
The goals module consists of:
- exercises - predefined actions which should be performed by patient. Exercises can be managed only by SuperAdmin,
- goals - objectives defined for each patient which could consists of exercises, grips and grip switches,
- goal conditions - parts of the goal, single condition of type exercise, grips goal or switches goal.
List grips
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/grips?model=1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/grips"
);
const params = {
"model": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 1,
"number": 3551,
"name": "numquam grip",
"description": null,
"opposed": 0,
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
},
{
"id": 2,
"number": 8615,
"name": "nulla grip",
"description": null,
"opposed": 0,
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view grips",
"code": "GOALS:LIST_GRIPS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List exercises
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/exercises" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/exercises"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"name": "exercises.Gwendolyn Island",
"description": "exercises.Architecto quod quia ipsum ipsam.",
"icon": "😆",
"created_at": "2026-02-27T12:42:46.000000Z",
"updated_at": "2026-02-27T12:42:46.000000Z"
},
{
"id": 2,
"name": "exercises.Torp Road",
"description": "exercises.Possimus possimus laboriosam eum unde.",
"icon": "😔",
"created_at": "2026-02-27T12:42:46.000000Z",
"updated_at": "2026-02-27T12:42:46.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view exercises",
"code": "GOALS:LIST_EXERCISES:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create exercise
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/exercises" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Water plants\",
\"description\": \"Use Tripod Close Grip and water your plants\",
\"icon\": \"🪴\"
}"
const url = new URL(
"http://localhost:8000/api/exercises"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Water plants",
"description": "Use Tripod Close Grip and water your plants",
"icon": "🪴"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 3,
"name": "exercises.Elmira Drive",
"description": "exercises.Aliquam corrupti a architecto cum maxime ut.",
"icon": "😱",
"created_at": "2026-02-27T12:42:46.000000Z",
"updated_at": "2026-02-27T12:42:46.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage exercises",
"code": "GOALS:CREATE_EXERCISE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update exercise
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/exercises/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Water plants\",
\"description\": \"Use Tripod Close Grip and water your plants\",
\"icon\": \"🪴\"
}"
const url = new URL(
"http://localhost:8000/api/exercises/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Water plants",
"description": "Use Tripod Close Grip and water your plants",
"icon": "🪴"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 4,
"name": "exercises.Elwyn Roads",
"description": "exercises.Ea necessitatibus quae et qui corrupti.",
"icon": "😜",
"created_at": "2026-02-27T12:42:46.000000Z",
"updated_at": "2026-02-27T12:42:46.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage exercises",
"code": "GOALS:UPDATE_EXERCISE:INSUFFICIENT_PERMISSION"
}
Example response (404, Exercise not found):
{
"message": "Exercise not found",
"code": "GOALS:UPDATE_EXERCISE:EXERCISE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete exercise
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/exercises/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/exercises/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Exercise deleted",
"code": "GOALS:DELETE_EXERCISE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage exercises",
"code": "GOALS:DELETE_EXERCISE:INSUFFICIENT_PERMISSION"
}
Example response (403, Exercise is used in goals):
{
"message": "Cannot delete: exercise is used in goals (1)",
"code": "GOALS:DELETE_EXERCISE:HAS_GOALS"
}
Example response (404, Exercise not found):
{
"message": "Exercise not found",
"code": "GOALS:DELETE_EXERCISE:EXERCISE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List user goals
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/user/1/goals?active=1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/user/1/goals"
);
const params = {
"active": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"amputee_id": 258,
"clinician_id": 259,
"start_date": "1980-05-11",
"end_date": "1987-11-18",
"active": 0,
"created_at": "2026-02-27T12:42:46.000000Z",
"updated_at": "2026-02-27T12:42:46.000000Z"
},
{
"id": 2,
"amputee_id": 260,
"clinician_id": 261,
"start_date": "2000-11-19",
"end_date": "2008-11-14",
"active": 1,
"created_at": "2026-02-27T12:42:46.000000Z",
"updated_at": "2026-02-27T12:42:46.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view user goals",
"code": "GOALS:LIST_GOALS:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "GOALS:LIST_GOALS:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create user goal
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/user/1/goals" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"start_date\": \"2023-05-12\",
\"end_date\": \"2023-05-15\",
\"active\": true
}"
const url = new URL(
"http://localhost:8000/api/user/1/goals"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"start_date": "2023-05-12",
"end_date": "2023-05-15",
"active": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 3,
"amputee_id": 262,
"clinician_id": 263,
"start_date": "2007-07-25",
"end_date": "1971-10-18",
"active": 1,
"created_at": "2026-02-27T12:42:46.000000Z",
"updated_at": "2026-02-27T12:42:46.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage user goals",
"code": "GOALS:CREATE_GOAL:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "GOALS:CREATE_GOAL:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update user goal
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/user/1/goals/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"start_date\": \"2023-05-12\",
\"end_date\": \"2023-05-15\",
\"active\": true
}"
const url = new URL(
"http://localhost:8000/api/user/1/goals/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"start_date": "2023-05-12",
"end_date": "2023-05-15",
"active": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 4,
"amputee_id": 264,
"clinician_id": 265,
"start_date": "2021-10-10",
"end_date": "2019-09-20",
"active": 0,
"created_at": "2026-02-27T12:42:46.000000Z",
"updated_at": "2026-02-27T12:42:46.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage user goals",
"code": "GOALS:UPDATE_GOAL:INSUFFICIENT_PERMISSION"
}
Example response (403, Cannot activate ongoing goal):
{
"message": "Cannot activate ongoing goal",
"code": "GOALS:UPDATE_GOAL:GOAL_IS_ONGOING"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "GOALS:UPDATE_GOAL:USER_NOT_FOUND"
}
Example response (404, Goal not found):
{
"message": "Goal not found",
"code": "GOALS:UPDATE_GOAL:GOAL_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete user goal
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/user/1/goals/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/user/1/goals/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Goal deleted",
"code": "GOALS:DELETE_GOAL:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage user goals",
"code": "GOALS:DELETE_GOAL:INSUFFICIENT_PERMISSION"
}
Example response (403, Cannot delete ongoing goal):
{
"message": "Cannot delete active ongoing goal",
"code": "GOALS:DELETE_GOAL:GOAL_IS_ONGOING"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "GOALS:DELETE_GOAL:USER_NOT_FOUND"
}
Example response (404, Goal not found):
{
"message": "Goal not found",
"code": "GOALS:DELETE_GOAL:GOAL_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List user goal conditions
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/user/1/goals/1/conditions" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/user/1/goals/1/conditions"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"goal_id": 5,
"type": "exercise",
"grip_id": 3,
"grips_frequency": "m",
"grips_count": 922,
"switches_frequency": "w",
"switches_count": 295,
"exercise_id": 5,
"exercise_frequency": "d",
"exercise_count": 3,
"created_at": "2026-02-27T12:42:47.000000Z",
"updated_at": "2026-02-27T12:42:47.000000Z"
},
{
"id": 2,
"goal_id": 6,
"type": "exercise",
"grip_id": 4,
"grips_frequency": "w",
"grips_count": 150,
"switches_frequency": "m",
"switches_count": 570,
"exercise_id": 6,
"exercise_frequency": "m",
"exercise_count": 8,
"created_at": "2026-02-27T12:42:47.000000Z",
"updated_at": "2026-02-27T12:42:47.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view user goals",
"code": "GOALS:LIST_CONDITIONS:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "GOALS:LIST_CONDITIONS:USER_NOT_FOUND"
}
Example response (404, Goal not found):
{
"message": "Goal not found",
"code": "GOALS:LIST_CONDITIONS:GOAL_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create user goal condition
requires authentication
Each goal condition could be one of type: grip, switch or exercise.
If goal condition is type of grip, fill only grip_id (optional), grips_frequency and grips_count.
If grip_id is null or missing, patient can perform any grip to fulfill objective.
If goal condition is type of switch, fill only switches_frequency and switches_count.
If goal condition is type of exercise, fill only exercise_id, exercise_frequency and exercise_count.
Restrictions:
- you can add one grip-any condition (
grip_id=null, any grip is counted) and many grip-specific conditions (for example: grip 1 - 100 times and grip 2 - 50 times), - all grips conditions must have same frequency (
grips_frequencyfield), - sum of grip-specific conditions (
grips_countfield) cannot be greater than grip-any condition for same goal - you can add only one switch condition for same goal,
- you can add multiple exercise conditions, but each exercise can be used only once.
Example request:
curl --request POST \
"http://localhost:8000/api/user/1/goals/1/conditions" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"type\": \"grip\",
\"grip_id\": 1,
\"grips_frequency\": \"d\",
\"grips_count\": 100,
\"switches_frequency\": \"d\",
\"switches_count\": 100,
\"exercise_id\": 1,
\"exercise_frequency\": \"d\",
\"exercise_count\": 5
}"
const url = new URL(
"http://localhost:8000/api/user/1/goals/1/conditions"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"type": "grip",
"grip_id": 1,
"grips_frequency": "d",
"grips_count": 100,
"switches_frequency": "d",
"switches_count": 100,
"exercise_id": 1,
"exercise_frequency": "d",
"exercise_count": 5
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 3,
"goal_id": 7,
"type": "grip",
"grip_id": 5,
"grips_frequency": "d",
"grips_count": 956,
"switches_frequency": "m",
"switches_count": 780,
"exercise_id": 7,
"exercise_frequency": "m",
"exercise_count": 2,
"created_at": "2026-02-27T12:42:47.000000Z",
"updated_at": "2026-02-27T12:42:47.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage user goals",
"code": "GOALS:CREATE_CONDITION:INSUFFICIENT_PERMISSION"
}
Example response (403, Cannot create condition: all grip conditions have to be same frequency):
{
"message": "Cannot create condition: all grip conditions have to be same frequency",
"code": "GOALS:CREATE_CONDITION:INVALID_FREQUENCY"
}
Example response (403, Cannot create condition: grip-any condition for this goal already exist):
{
"message": "Cannot create condition: grip-any condition for this goal already exist",
"code": "GOALS:CREATE_CONDITION:GRIP_ANY_ALREADY_EXISTS"
}
Example response (403, Cannot create condition: condition with this grip already exist):
{
"message": "Cannot create condition: condition with this grip already exist",
"code": "GOALS:CREATE_CONDITION:GRIP_CONDITION_ALREADY_EXISTS"
}
Example response (403, Cannot create condition: grip-any value cannot be lower than sum of grip-specific conditions):
{
"message": "Cannot create condition: grip-any value cannot be lower than sum of grip-specific conditions",
"code": "GOALS:CREATE_CONDITION:GRIP_ANY_LOWER_THAN_GRIPS_SUM"
}
Example response (403, Cannot create condition: sum of grip-specific conditions cannot be greater than value of grip-any condition):
{
"message": "Cannot create condition: sum of grip-specific conditions cannot be greater than value of grip-any condition",
"code": "GOALS:CREATE_CONDITION:GRIPS_SUM_GREATER_THAN_GRIP_ANY"
}
Example response (403, Cannot create condition: switch condition for this goal already exist):
{
"message": "Cannot create condition: switch condition for this goal already exist",
"code": "GOALS:CREATE_CONDITION:SWITCH_CONDITION_ALREADY_EXISTS"
}
Example response (403, Cannot create condition: condition with this exercise already exist):
{
"message": "Cannot create condition: condition with this exercise already exist",
"code": "GOALS:CREATE_CONDITION:EXERCISE_CONDITION_ALREADY_EXISTS"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "GOALS:CREATE_CONDITION:USER_NOT_FOUND"
}
Example response (404, Goal not found):
{
"message": "Goal not found",
"code": "GOALS:CREATE_CONDITION:GOAL_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete user goal condition
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/user/1/goals/1/conditions/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/user/1/goals/1/conditions/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Goal condition deleted",
"code": "GOALS:DELETE_CONDITION:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage user goals",
"code": "GOALS:DELETE_CONDITION:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "GOALS:DELETE_CONDITION:USER_NOT_FOUND"
}
Example response (404, Goal not found):
{
"message": "Goal not found",
"code": "GOALS:DELETE_CONDITION:GOAL_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get user goal progress
requires authentication
grips- data about grips progress,switches- data about switches progress,exercises- data about exercises progress and attempts made.
overall- summary of whole goal time-frame,period- summary of given period, according to frequency (for example: if frequency of conditions is "weekly", these data is summary of current's week).today- summary of today's, used mainly to send daily summary notifications,conditions- goal conditions with progress for each one.
typefor grips overall summary, which points which conditions were used to calculate the summary. If grip-any condition exists, it has priority over grip-specific conditions, otherwise summary contains sum of all grip-specific conditions,frequency,frequency_fromandfrequency_tofor period summary for both grips and switches, which describe time-frame of frequency and period,donefor today's summary for both grips and switches, indicates if today's goal is reached (it's calculated only for conditions of frequency "daily").
Example request:
curl --request GET \
--get "http://localhost:8000/api/goals/1/progress" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/goals/1/progress"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"grips": {
"meta": {
"overall": {
"from": "2023-09-01 00:00:00",
"to": "2023-08-30 23:59:59"
},
"period": {
"from": "2023-09-15 23:59:59",
"to": "2023-09-21 23:59:59",
"frequency": "w"
}
},
"summary": {
"type": "grips-specific",
"progress": 222,
"goal": 2535
},
"progress": [
{
"grip": {
"id": 1,
"number": 0,
"name": "Rest Opposition",
"description": null,
"created_at": "2023-08-30T12:20:00.000000Z",
"updated_at": "2023-08-30T12:20:00.000000Z"
},
"overall": {
"progress": 125,
"goal": 200
},
"period": {
"progress": 22,
"goal": 50
}
},
{
"grip": {
"id": 2,
"number": 1,
"name": "Power",
"description": null,
"created_at": "2023-05-18T11:24:11.000000Z",
"updated_at": "2023-05-18T11:24:11.000000Z"
},
"overall": {
"progress": 90,
"goal": 150
},
"period": {
"progress": 10,
"goal": 30
}
},
{
"grip": null,
"overall": {
"progress": 78,
"goal": 1250
},
"period": {
"progress": 17,
"goal": 240
}
}
],
"today": {
"performed": 0,
"goal": 0,
"done": true
}
},
"switches": {
"overall": {
"performed": 55,
"goal": 300
},
"period": {
"performed": 25,
"goal": 30,
"frequency": "d",
"frequency_from": "2023-09-20 00:00:00",
"frequency_to": "2023-09-20 23:59:59"
},
"today": {
"performed": 25,
"goal": 30,
"done": false
},
"condition": {
"type": "switch",
"switches_frequency": "d",
"switches_count": 30
}
},
"exercises": {
"performed": 1,
"goal": 3,
"done": false,
"conditions": [
{
"type": "exercise",
"exercise_id": 1,
"exercise_frequency": "d",
"exercise_count": 3,
"attempts": [
{
"date_from": "2023-06-06",
"date_to": "2023-06-12",
"count_done": 1,
"count_not_done": 1
},
{
"date_from": "2023-06-13",
"date_to": "2023-06-19",
"count_done": 0,
"count_not_done": 0
},
{
"date_from": "2023-06-20",
"date_to": "2023-06-26",
"count_done": 0,
"count_not_done": 0
},
{
"date_from": "2023-06-27",
"date_to": "2023-07-03",
"count_done": 0,
"count_not_done": 0
}
],
"exercise": {
"id": 1,
"name": "Water plants",
"description": "Use Tripod Grip and water your plants",
"icon": "🪴",
"created_at": "2023-05-19T10:25:37.000000Z",
"updated_at": "2023-05-19T10:25:37.000000Z"
}
}
]
}
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view goal progress",
"code": "GOALS:GET_PROGRESS:INSUFFICIENT_PERMISSION"
}
Example response (404, Goal not found):
{
"message": "Goal not found",
"code": "GOALS:GET_PROGRESS:GOAL_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update user goal progress
requires authentication
Use this endpoint to update goal progress as patient. Add exercise attempts and mark them as done or not done.
Example request:
curl --request POST \
"http://localhost:8000/api/goals/1/progress" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"exercise_id\": 1,
\"exercise_done\": true
}"
const url = new URL(
"http://localhost:8000/api/goals/1/progress"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"exercise_id": 1,
"exercise_done": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 1,
"user_id": 272,
"goal_id": 8,
"type": "switch",
"grip_id": null,
"grips": 880,
"switches": 643,
"exercise_id": 8,
"exercise_done": 0,
"created_at": "2026-02-27T12:42:47.000000Z",
"updated_at": "2026-02-27T12:42:47.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update goal progress",
"code": "GOALS:UPDATE_PROGRESS:INSUFFICIENT_PERMISSION"
}
Example response (404, Goal not found):
{
"message": "Goal not found",
"code": "GOALS:UPDATE_PROGRESS:GOAL_NOT_FOUND"
}
Example response (422, User timezone not set):
{
"message": "User timezone not set",
"code": "GOALS:UPDATE_PROGRESS:NO_TIMEZONE"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Invitations
Accept clinician invitation
Example request:
curl --request POST \
"http://localhost:8000/api/invite/accept" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"token\": \"ABC123DEF456GHI789JKL0\",
\"email\": \"example@domain.com\",
\"password\": \"Test123!\",
\"language\": \"en\",
\"name\": \"Tom Smith\",
\"clinic_name\": \"My clinic Ltd\",
\"clinic_location\": \"Example St 1\\/345 New York, NY\",
\"address1\": \"98855 Leuschke Well\",
\"address2\": \"North Titohaven, OR 69695-2793\",
\"mfa_enabled\": true,
\"mfa_method\": \"email\"
}"
const url = new URL(
"http://localhost:8000/api/invite/accept"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"token": "ABC123DEF456GHI789JKL0",
"email": "example@domain.com",
"password": "Test123!",
"language": "en",
"name": "Tom Smith",
"clinic_name": "My clinic Ltd",
"clinic_location": "Example St 1\/345 New York, NY",
"address1": "98855 Leuschke Well",
"address2": "North Titohaven, OR 69695-2793",
"mfa_enabled": true,
"mfa_method": "email"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"id": 4,
"mrn": "87CAM8XE1772196141",
"name": "Marge Paucek",
"email": "1772196141janick81@example.net",
"language": "en",
"phone": "(231) 667-8183",
"phone_country": "VN",
"phone_verified_at": null,
"address1": "597 Hoeger Roads",
"address2": "East Ramiro, NY 18914",
"postal_code": "27176",
"city": "Sipes-Beahan",
"country": "IT",
"clinic_name": "Shaynaville",
"clinic_location": "62122 Barton Prairie\nSouth Monserratfort, NE 87894",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:21.000000Z",
"updated_at": "2026-02-27T12:42:21.000000Z",
"invitation_status": "accepted",
"acadle_invitation_status": null,
"roles": [
{
"id": 4,
"name": "ClinicianSupport"
}
]
}
Example response (403, Invitation expired):
{
"message": "Invitation expired",
"code": "INVITATIONS:ACCEPT:INVITATION_EXPIRED"
}
Example response (404, Invitation not found):
{
"message": "Invitation not found",
"code": "INVITATIONS:ACCEPT:INVITATION_NOT_FOUND"
}
Example response (500, Server error):
{
"message": "Server error: invitation not accepted",
"code": "INVITATIONS:ACCEPT:SERVER_ERROR"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Accept Acadle invitation
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/invite/acadle/accept" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"token\": \"a1b2c3d4e5f6g7h8i9j0k1l2m3\",
\"email\": \"user@example.com\",
\"password\": \"securePassword123\",
\"phone\": \"559.389.8603\",
\"phone_country\": \"US\",
\"name\": \"John Doe\",
\"language\": \"en\"
}"
const url = new URL(
"http://localhost:8000/api/invite/acadle/accept"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"token": "a1b2c3d4e5f6g7h8i9j0k1l2m3",
"email": "user@example.com",
"password": "securePassword123",
"phone": "559.389.8603",
"phone_country": "US",
"name": "John Doe",
"language": "en"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"id": 5,
"mrn": "Y3B9OUN61772196141",
"name": "Prof. Warren Hackett",
"email": "1772196141domenick.berge@example.net",
"language": "en",
"phone": "+1 (412) 359-2455",
"phone_country": "NU",
"phone_verified_at": null,
"address1": "17451 Elaina Junctions Suite 908",
"address2": "Barryside, NH 38339-0692",
"postal_code": "43938",
"city": "Quigley, O'Hara and Jacobi",
"country": "HU",
"clinic_name": "O'Connerburgh",
"clinic_location": "8577 Howell Meadow\nRettaville, DE 83384-5677",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:21.000000Z",
"updated_at": "2026-02-27T12:42:21.000000Z",
"invitation_status": "accepted",
"acadle_invitation_status": null,
"roles": [
{
"id": 4,
"name": "ClinicianSupport"
}
]
}
Example response (403, Invitation expired):
{
"message": "Invitation expired",
"code": "INVITATIONS_ACADLE:ACCEPT:INVITATION_EXPIRED"
}
Example response (404, Invitation not found):
{
"message": "Invitation not found",
"code": "INVITATIONS_ACADLE:ACCEPT:INVITATION_NOT_FOUND"
}
Example response (500, Server error):
{
"message": "Server error: invitation not accepted",
"code": "INVITATIONS_ACADLE:ACCEPT:SERVER_ERROR"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List users for invitations
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/invite/users" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/invite/users"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 15,
"mrn": "MZPXEA9W1772196143",
"name": "Lupe Daugherty",
"email": "1772196143runolfsdottir.harvey@example.com",
"language": "en",
"phone": "1-229-346-2529",
"phone_country": "GH",
"phone_verified_at": null,
"address1": "614 Romaguera Forges Suite 747",
"address2": "Bednarport, CO 41201-7898",
"postal_code": "17627",
"city": "Heathcote-Boyer",
"country": "GR",
"clinic_name": "Lake Rupert",
"clinic_location": "7435 Santos Way\nNew Marisamouth, ME 18796",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:23.000000Z",
"updated_at": "2026-02-27T12:42:23.000000Z",
"invitation_status": "accepted",
"acadle_invitation_status": null,
"roles": [
{
"id": 3,
"name": "Clinician"
}
]
},
{
"id": 16,
"mrn": "PGFYVFFR1772196143",
"name": "Elenor Abernathy",
"email": "1772196143considine.susanna@example.net",
"language": "en",
"phone": "917.657.1527",
"phone_country": "BL",
"phone_verified_at": null,
"address1": "488 Schroeder Mission Suite 614",
"address2": "Deckowfurt, TX 60723-4882",
"postal_code": "34199",
"city": "Boehm-Borer",
"country": "IE",
"clinic_name": "Lake Kip",
"clinic_location": "844 Carter Extensions Apt. 066\nMacejkovicmouth, LA 12953-0109",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:23.000000Z",
"updated_at": "2026-02-27T12:42:23.000000Z",
"invitation_status": null,
"acadle_invitation_status": "accepted",
"roles": [
{
"id": 6,
"name": "AcadleUser"
}
]
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list users for invitations",
"code": "INVITATIONS:USERS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create clinician invitations
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/invite" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"patient_id\": 1,
\"invitations\": [
{
\"user_id\": 1,
\"user_email\": \"newuser@domain.com\",
\"role\": \"Clinician\",
\"training_confirmed\": true,
\"permissions\": [
\"voluptates\"
]
}
]
}"
const url = new URL(
"http://localhost:8000/api/invite"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"patient_id": 1,
"invitations": [
{
"user_id": 1,
"user_email": "newuser@domain.com",
"role": "Clinician",
"training_confirmed": true,
"permissions": [
"voluptates"
]
}
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 10,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 17,
"mrn": "RLGNBOTD1772196143",
"name": "Alexzander Halvorson II",
"email": "1772196143brigitte92@example.org",
"language": "en",
"phone": "+1-848-528-9301",
"phone_country": "IS",
"phone_verified_at": null,
"address1": "7335 Yost Burgs",
"address2": "Jessycaville, UT 75852-1133",
"postal_code": "06513",
"city": "Bruen-Jerde",
"country": "IT",
"clinic_name": "Kaceyland",
"clinic_location": "643 Stoltenberg Path\nReymundofort, MA 67805-5445",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:23.000000Z",
"updated_at": "2026-02-27T12:42:23.000000Z",
"invitation_status": "accepted",
"acadle_invitation_status": null,
"invitations": [
{
"id": 1,
"user_id": 18,
"invited_user_id": 17,
"type": "clinician",
"training_confirmed": 0,
"created_at": "2026-02-27T12:42:24.000000Z",
"updated_at": "2026-02-27T12:42:24.000000Z"
}
],
"roles": [
{
"id": 3,
"name": "Clinician"
}
]
},
{
"id": 20,
"mrn": "UUGZZ1VA1772196144",
"name": "Coralie Cummerata",
"email": "1772196144arden80@example.net",
"language": "en",
"phone": "949-565-6024",
"phone_country": "PY",
"phone_verified_at": null,
"address1": "4732 Watsica Unions",
"address2": "Leannonmouth, TX 87205",
"postal_code": "91707",
"city": "Fisher, Pfeffer and Kling",
"country": "IN",
"clinic_name": "Port Tyrahaven",
"clinic_location": "44329 Boyle Roads\nPort Bernie, AZ 43931-9586",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:24.000000Z",
"updated_at": "2026-02-27T12:42:24.000000Z",
"invitation_status": "accepted",
"acadle_invitation_status": null,
"invitations": [
{
"id": 2,
"user_id": 21,
"invited_user_id": 20,
"type": "clinician",
"training_confirmed": 1,
"created_at": "2026-02-27T12:42:24.000000Z",
"updated_at": "2026-02-27T12:42:24.000000Z"
}
],
"roles": [
{
"id": 4,
"name": "ClinicianSupport"
}
]
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create invitations",
"code": "INVITATIONS:CREATE:INSUFFICIENT_PERMISSION"
}
Example response (403, No access to given patient):
{
"message": "No access to given patient",
"code": "INVITATIONS:CREATE:NO_ACCESS_TO_PATIENT"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Resend invitation
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/invite/1/resend" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/invite/1/resend"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (201):
{
"id": 23,
"mrn": "ZNDONS601772196144",
"name": "Daphney Lueilwitz",
"email": "1772196144una26@example.org",
"language": "en",
"phone": "1-651-708-7684",
"phone_country": "TK",
"phone_verified_at": null,
"address1": "2302 Kirlin Bypass Suite 241",
"address2": "East Mikaylaville, OH 51919-3791",
"postal_code": "52919-6948",
"city": "Morissette Ltd",
"country": "CY",
"clinic_name": "Jakefort",
"clinic_location": "8085 Efrain Island\nLake Gloria, WY 41163",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:24.000000Z",
"updated_at": "2026-02-27T12:42:24.000000Z",
"invitation_status": "accepted",
"acadle_invitation_status": null,
"invitations": [
{
"id": 3,
"user_id": 24,
"invited_user_id": 23,
"type": "clinician",
"training_confirmed": 1,
"created_at": "2026-02-27T12:42:24.000000Z",
"updated_at": "2026-02-27T12:42:24.000000Z"
}
],
"roles": [
{
"id": 3,
"name": "Clinician"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to resend invitations",
"code": "INVITATIONS:RESEND:INSUFFICIENT_PERMISSION"
}
Example response (403, User not found):
{
"message": "User not found",
"code": "INVITATIONS:RESEND:USER_NOT_FOUND"
}
Example response (403, Invitation already accepted):
{
"message": "Invitation already accepted",
"code": "INVITATIONS:RESEND:INVITATION_ALREADY_ACCEPTED"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List all users invited to Acadle
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/invite/acadle/users?search=john" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/invite/acadle/users"
);
const params = {
"search": "john",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 26,
"mrn": "YT3U0CTQ1772196144",
"name": "Felicita Herman",
"email": "1772196144parker.ansel@example.com",
"language": "en",
"phone": "559.904.6297",
"phone_country": "WF",
"phone_verified_at": null,
"address1": "988 Royce Neck Apt. 824",
"address2": "East Brigitte, PA 44375",
"postal_code": "71722",
"city": "Roob, Reichel and Padberg",
"country": "PL",
"clinic_name": "Port Alexa",
"clinic_location": "175 Isai Place Apt. 910\nLake Allen, KS 58689-1507",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:24.000000Z",
"updated_at": "2026-02-27T12:42:24.000000Z",
"invitation_status": "accepted",
"acadle_invitation_status": null,
"roles": [
{
"id": 3,
"name": "Clinician"
}
]
},
{
"id": 27,
"mrn": "FUDVQ1501772196144",
"name": "Prof. Alexandria Schowalter MD",
"email": "1772196144metz.shayna@example.net",
"language": "en",
"phone": "(979) 349-2257",
"phone_country": "PR",
"phone_verified_at": null,
"address1": "3853 Borer Greens",
"address2": "Schambergerfort, MT 73988-0889",
"postal_code": "85863",
"city": "Kuhic-Gusikowski",
"country": "CY",
"clinic_name": "North Julianne",
"clinic_location": "33061 Katheryn Wall\nGilbertotown, VA 60755",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:24.000000Z",
"updated_at": "2026-02-27T12:42:24.000000Z",
"invitation_status": "accepted",
"acadle_invitation_status": null,
"roles": [
{
"id": 4,
"name": "ClinicianSupport"
}
]
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list users for invitations",
"code": "INVITATIONS_ACADLE:USERS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create Acadle invitation
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/invite/acadle" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"jerald56@example.com\"
}"
const url = new URL(
"http://localhost:8000/api/invite/acadle"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "jerald56@example.com"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 28,
"mrn": "NRJY2Z7N1772196144",
"name": "Dina Herzog I",
"email": "1772196144francisco.herzog@example.org",
"language": "en",
"phone": "+1-208-565-7013",
"phone_country": "TN",
"phone_verified_at": null,
"address1": "512 Klein Shore Suite 277",
"address2": "Favianbury, DE 92000",
"postal_code": "51222-1754",
"city": "Sporer, Hodkiewicz and Lockman",
"country": "RO",
"clinic_name": "Schummberg",
"clinic_location": "81637 Sadie Dale Suite 825\nPort Dessie, RI 15577",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:24.000000Z",
"updated_at": "2026-02-27T12:42:24.000000Z",
"invitation_status": null,
"acadle_invitation_status": "accepted",
"invitations": [
{
"id": 4,
"user_id": 29,
"invited_user_id": 28,
"type": "clinician",
"training_confirmed": 0,
"created_at": "2026-02-27T12:42:24.000000Z",
"updated_at": "2026-02-27T12:42:24.000000Z"
}
],
"roles": [
{
"id": 6,
"name": "AcadleUser"
}
]
}
Example response (400, User already exists):
{
"message": "User with this email already exists in the system",
"code": "INVITATIONS_ACADLE:CREATE:USER_ALREADY_EXISTS"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create invitations",
"code": "INVITATIONS_ACADLE:CREATE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Resend Acadle invitation
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/invite/acadle/1/resend" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/invite/acadle/1/resend"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (201):
{
"id": 31,
"mrn": "VG2X4FT81772196145",
"name": "Mike Glover",
"email": "1772196145susana.parker@example.net",
"language": "en",
"phone": "1-240-496-9774",
"phone_country": "RW",
"phone_verified_at": null,
"address1": "4176 Dena Underpass Suite 854",
"address2": "New Helgafort, AK 22447-2537",
"postal_code": "29592",
"city": "Murazik, Spencer and Heathcote",
"country": "GB",
"clinic_name": "South Dominicburgh",
"clinic_location": "913 Bernhard Station\nArmstrongchester, DE 09769",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z",
"invitation_status": "accepted",
"acadle_invitation_status": null,
"invitations": [
{
"id": 5,
"user_id": 32,
"invited_user_id": 31,
"type": "clinician",
"training_confirmed": 1,
"created_at": "2026-02-27T12:42:25.000000Z",
"updated_at": "2026-02-27T12:42:25.000000Z"
}
],
"roles": [
{
"id": 2,
"name": "ClinicAdmin"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to resend invitations",
"code": "INVITATIONS_ACADLE:RESEND:INSUFFICIENT_PERMISSION"
}
Example response (403, User not found):
{
"message": "User not found",
"code": "INVITATIONS_ACADLE:RESEND:USER_NOT_FOUND"
}
Example response (403, Invitation already accepted):
{
"message": "Invitation already accepted",
"code": "INVITATIONS_ACADLE:RESEND:INVITATION_ALREADY_ACCEPTED"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Admin access to invitation tokens
requires authentication
Requires admin.invitations_tokens_access permission.
Fetches only non-accepted and non-expired invitations.
Example request:
curl --request GET \
--get "http://localhost:8000/api/invite/tokens/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/invite/tokens/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
[
{
"id": 1,
"user_id": 1,
"invited_user_id": 2,
"token": "I0V25NUVMHC0F8RRF1YEY5BT",
"training_confirmed": 1,
"created_at": "2025-05-12T12:00:00.000000Z",
"updated_at": "2025-05-12T12:00:00.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to get invitation tokens",
"code": "INVITATIONS:ADMIN_TOKENS:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "INVITATIONS:ADMIN_TOKENS:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Logs
API endpoints for managing event logs
Get events log
requires authentication
user - user account that performed the action
element - element model that has been affected by the action
Example request:
curl --request GET \
--get "http://localhost:8000/api/logs?search=Test&ip=200.200.100.5&user=1&type=user&date_from=1642003200&date_to=1642003200&include_sessions=1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
const url = new URL(
"http://localhost:8000/api/logs"
);
const params = {
"search": "Test",
"ip": "200.200.100.5",
"user": "1",
"type": "user",
"date_from": "1642003200",
"date_to": "1642003200",
"include_sessions": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"user_id": 277,
"event_name": "event_factory",
"element_type": "App\\Models\\User",
"element_id": 276,
"comments": "",
"ip_address": "225.238.28.20",
"created_at": "1997-05-22T18:23:24.000000Z",
"updated_at": "2026-02-27T12:42:48.000000Z",
"user": {
"id": 277,
"mrn": "O51KHHDC1772196167",
"name": "Ernie Stehr",
"email": "1772196167wbradtke@example.com",
"language": "en",
"phone": "+1-531-746-8238",
"phone_country": "US",
"phone_verified_at": null,
"address1": "396 Melany Knolls Suite 018",
"address2": "Homenickmouth, AK 36437-9227",
"postal_code": "40766-0725",
"city": "Schuppe Ltd",
"country": "HU",
"clinic_name": "Natashafurt",
"clinic_location": "86711 West Square\nGislasonstad, ND 89124-8659",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:48.000000Z",
"updated_at": "2026-02-27T12:42:48.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"element": {
"id": 276,
"mrn": "FOPY4WSI1772196167",
"name": "Elmo Nicolas",
"email": "1772196167huels.beulah@example.org",
"language": "en",
"phone": "+1 (618) 907-9826",
"phone_country": "IQ",
"phone_verified_at": null,
"address1": "2700 Johnson Streets",
"address2": "Brownport, WI 59749",
"postal_code": "18830",
"city": "Conroy, Mayer and Nicolas",
"country": "LV",
"clinic_name": "Michealshire",
"clinic_location": "635 Rosenbaum Garden\nWest Amira, WV 97450-1039",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:47.000000Z",
"updated_at": "2026-02-27T12:42:47.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
},
{
"id": 2,
"user_id": 280,
"event_name": "event_factory",
"element_type": "App\\Models\\User",
"element_id": 279,
"comments": "",
"ip_address": "59.162.110.42",
"created_at": "1998-06-29T15:23:51.000000Z",
"updated_at": "2026-02-27T12:42:48.000000Z",
"user": {
"id": 280,
"mrn": "GR8TNWS31772196168",
"name": "Litzy Abernathy IV",
"email": "1772196168price.era@example.org",
"language": "en",
"phone": "1-586-927-3002",
"phone_country": "TO",
"phone_verified_at": null,
"address1": "8060 Zoe Motorway",
"address2": "East Odie, NH 76860-5171",
"postal_code": "09158-3173",
"city": "Keebler, Langworth and Thompson",
"country": "HR",
"clinic_name": "West Nelleshire",
"clinic_location": "903 Gusikowski Rapid\nWest Doug, AZ 02235",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:48.000000Z",
"updated_at": "2026-02-27T12:42:48.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"element": {
"id": 279,
"mrn": "VFXSLSFX1772196168",
"name": "Tabitha Runolfsson DVM",
"email": "1772196168oconnelly@example.net",
"language": "en",
"phone": "562-775-4888",
"phone_country": "BS",
"phone_verified_at": null,
"address1": "788 Elizabeth Landing",
"address2": "Pfefferside, WY 18620",
"postal_code": "33264-3630",
"city": "Homenick-Torphy",
"country": "SK",
"clinic_name": "West Candidaport",
"clinic_location": "7062 Elna Run Suite 662\nRauborough, NH 87073-4179",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:48.000000Z",
"updated_at": "2026-02-27T12:42:48.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
}
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to access event logs",
"code": "EVENT_LOGS:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Messages
API endpoints for message center
Get user messages list
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/messages" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"filter\": \"all\"
}"
const url = new URL(
"http://localhost:8000/api/messages"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"filter": "all"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"user_id": null,
"message_id": 1,
"is_read": 0,
"is_archived": 0,
"is_deleted": 0,
"message": {
"id": 1,
"sender_id": null,
"title": "Corporis est vel beatae qui.",
"content": "Sit voluptas possimus qui qui amet veniam odio.",
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z",
"sender": null
}
},
{
"id": 2,
"user_id": null,
"message_id": 2,
"is_read": 0,
"is_archived": 0,
"is_deleted": 0,
"message": {
"id": 2,
"sender_id": null,
"title": "Iure quo consequuntur voluptatum.",
"content": "Nisi quia et reprehenderit asperiores.",
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z",
"sender": null
}
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Send message to multiple users
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/message" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"title\": \"Reminder about your vaccination\",
\"content\": \"Lorem ipsum dolor sit amet\",
\"roles\": \"Clinician,Amputee\"
}"
const url = new URL(
"http://localhost:8000/api/message"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"title": "Reminder about your vaccination",
"content": "Lorem ipsum dolor sit amet",
"roles": "Clinician,Amputee"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202, OK):
{
"message": "Messages sent",
"count": 3,
"code": "MESSAGES:SEND:SENT"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to send messages",
"code": "MESSAGES:SEND:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mark message as read
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/message/1/read" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"state\": true
}"
const url = new URL(
"http://localhost:8000/api/message/1/read"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"state": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 3,
"user_id": 143,
"message_id": 3,
"is_read": 0,
"is_archived": 0,
"is_deleted": 0
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to mark this message as read",
"code": "MESSAGES:READ:INSUFFICIENT_PERMISSION"
}
Example response (404, Message not found):
{
"message": "Message not found",
"code": "MESSAGES:READ:MESSAGE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mark message as archived
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/message/1/archive" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"state\": true
}"
const url = new URL(
"http://localhost:8000/api/message/1/archive"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"state": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 4,
"user_id": 144,
"message_id": 4,
"is_read": 0,
"is_archived": 0,
"is_deleted": 0
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to mark this message as archived",
"code": "MESSAGES:ARCHIVE:INSUFFICIENT_PERMISSION"
}
Example response (404, Message not found):
{
"message": "Message not found",
"code": "MESSAGES:ARCHIVE:MESSAGE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List of messages and tickets
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/messages-and-tickets" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/messages-and-tickets"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 2
},
"items": [
{
"type": "UserMessage",
"date": "2024-11-02T10:00:00.000000Z",
"item": {
"id": 1,
"user_id": 1,
"message_id": 1,
"is_read": 0,
"is_archived": 0,
"is_deleted": 0,
"message": {
"id": 1,
"sender_id": 1,
"title": "Message title",
"content": "Message content",
"created_at": "2024-11-02T10:00:00.000000Z",
"updated_at": "2024-11-02T10:00:00.000000Z",
"sender": {
"id": 1,
"mrn": "MRN",
"name": "User name",
"email": "user@domain.com",
"language": "en",
"phone": "",
"phone_verified_at": null,
"address1": "",
"address2": "",
"postal_code": "",
"city": "",
"clinic_name": "Test Company",
"clinic_location": "Test Company Location",
"image": null,
"mfa_enabled": 0,
"mfa_method": "email",
"mfa_verified_to": null,
"created_by": null,
"active": 1,
"notifications_timezone": "Europe/Warsaw",
"notifications_at": "08:00:00",
"created_at": "2024-09-01T15:00:00.000000Z",
"updated_at": "2024-10-10T10:30:00.000000Z",
"invitation_status": "accepted",
"roles": [
{
"id": 3,
"name": "Clinician",
"guard_name": "web",
"created_at": "2024-01-01T12:00:00.000000Z",
"updated_at": "2024-01-01T12:00:00.000000Z",
"pivot": {
"model_id": 1,
"role_id": 3,
"model_type": "App\\Models\\User"
}
}
]
}
}
}
},
{
"type": "SupportTicket",
"date": "2024-11-01T15:15:00.000000Z",
"item": {
"id": 1,
"sender_id": 1,
"recipient_id": 999,
"device_id": null,
"meeting_date": "2024-11-10T15:00:00.000000Z",
"meeting_type": "none",
"contact_email": null,
"status": "new",
"created_at": "2024-11-01T15:15:00.000000Z",
"updated_at": "2024-11-01T15:15:00.000000Z",
"sender": {
"id": 1,
"mrn": "MRN",
"name": "User name",
"email": "user@domain.com",
"language": "en",
"phone": "",
"phone_verified_at": null,
"address1": "",
"address2": "",
"postal_code": "",
"city": "",
"clinic_name": "Test Company",
"clinic_location": "Test Company Location",
"image": null,
"mfa_enabled": 0,
"mfa_method": "email",
"mfa_verified_to": null,
"created_by": null,
"active": 1,
"notifications_timezone": "Europe/Warsaw",
"notifications_at": "08:00:00",
"created_at": "2024-09-01T15:00:00.000000Z",
"updated_at": "2024-10-10T10:30:00.000000Z",
"invitation_status": "accepted",
"roles": [
{
"id": 3,
"name": "Clinician",
"guard_name": "web",
"created_at": "2024-01-01T12:00:00.000000Z",
"updated_at": "2024-01-01T12:00:00.000000Z",
"pivot": {
"model_id": 1,
"role_id": 3,
"model_type": "App\\Models\\User"
}
}
]
},
"recipient": {
"id": 2,
"mrn": "MRN2",
"name": "Patient",
"email": "patient4@domain.com",
"language": "en",
"phone": "",
"phone_verified_at": null,
"address1": "",
"address2": "",
"postal_code": "",
"city": "",
"clinic_name": null,
"clinic_location": null,
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"created_by": 1,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2024-10-01T15:00:00.000000Z",
"updated_at": "2024-10-10T10:30:00.000000Z",
"invitation_status": null,
"roles": [
{
"id": 5,
"name": "Amputee",
"guard_name": "web",
"created_at": "2024-01-01T12:00:00.000000Z",
"updated_at": "2024-01-01T12:00:00.000000Z",
"pivot": {
"model_id": 2,
"role_id": 5,
"model_type": "App\\Models\\User"
}
}
]
},
"device": null,
"messages": [
{
"id": 1,
"ticket_id": 1,
"sender_id": 1,
"title": "Communication channel",
"content": "Welcome to the digital platform. Please use this channel for communicating with your clinician.",
"is_read": false,
"created_at": "2024-11-01T15:15:00.000000Z",
"updated_at": "2024-11-01T15:15:00.000000Z",
"attachments": [],
"sender": {
"id": 1,
"mrn": "MRN",
"name": "User name",
"email": "user@domain.com",
"language": "en",
"phone": "",
"phone_verified_at": null,
"address1": "",
"address2": "",
"postal_code": "",
"city": "",
"clinic_name": "Test Company",
"clinic_location": "Test Company Location",
"image": null,
"mfa_enabled": 0,
"mfa_method": "email",
"mfa_verified_to": null,
"created_by": null,
"active": 1,
"notifications_timezone": "Europe/Warsaw",
"notifications_at": "08:00:00",
"created_at": "2024-09-01T15:00:00.000000Z",
"updated_at": "2024-10-10T10:30:00.000000Z",
"invitation_status": "accepted",
"roles": [
{
"id": 3,
"name": "Clinician",
"guard_name": "web",
"created_at": "2024-01-01T12:00:00.000000Z",
"updated_at": "2024-01-01T12:00:00.000000Z",
"pivot": {
"model_id": 1,
"role_id": 3,
"model_type": "App\\Models\\User"
}
}
]
}
}
]
}
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Status of messages and tickets
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/messages-and-tickets/status" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/messages-and-tickets/status"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"messages": 5,
"tickets": 2
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mobile logs
API endpoints for managing mobile logs
Store log
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/mobile-logs" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "device_id=1"\
--form "date_start=1982-10-29 04:58:26"\
--form "date_end=2013-03-16 10:37:20"\
--form "encrypt_key=et"\
--form "encrypt_iv=repudiandae"\
--form "file=@/tmp/phpYsZb4H" const url = new URL(
"http://localhost:8000/api/mobile-logs"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('device_id', '1');
body.append('date_start', '1982-10-29 04:58:26');
body.append('date_end', '2013-03-16 10:37:20');
body.append('encrypt_key', 'et');
body.append('encrypt_iv', 'repudiandae');
body.append('file', document.querySelector('input[name="file"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());Example response (202):
{
"id": 1,
"user_id": 281,
"device_id": 134,
"file": "/tmp/fakerTFJtnE",
"date_start": "1982-08-15 16:38:16",
"date_end": "2008-01-26 12:35:07",
"created_at": "2026-02-27T12:42:48.000000Z",
"updated_at": "2026-02-27T12:42:48.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to write mobile logs",
"code": "MOBILE_LOGS:STORE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get logs
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/mobile-logs" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/mobile-logs"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 2,
"user_id": 282,
"device_id": 135,
"file": "/tmp/fakerb1Q3RI",
"date_start": "1980-09-13 16:49:01",
"date_end": "2001-01-01 03:23:21",
"created_at": "2026-02-27T12:42:48.000000Z",
"updated_at": "2026-02-27T12:42:48.000000Z"
},
{
"id": 3,
"user_id": 283,
"device_id": 136,
"file": "/tmp/fakernQ4sqc",
"date_start": "2006-10-01 23:04:16",
"date_end": "2024-06-19 23:31:56",
"created_at": "2026-02-27T12:42:48.000000Z",
"updated_at": "2026-02-27T12:42:48.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view mobile logs",
"code": "MOBILE_LOGS:GET:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get logs by user
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/mobile-logs/user/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/mobile-logs/user/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 4,
"user_id": 284,
"device_id": 137,
"file": "/tmp/fakerjGWuaG",
"date_start": "1987-06-30 15:56:27",
"date_end": "1986-06-28 07:33:53",
"created_at": "2026-02-27T12:42:48.000000Z",
"updated_at": "2026-02-27T12:42:48.000000Z"
},
{
"id": 5,
"user_id": 285,
"device_id": 138,
"file": "/tmp/fakerPmgBfn",
"date_start": "2010-12-21 03:20:55",
"date_end": "2004-03-25 02:59:17",
"created_at": "2026-02-27T12:42:48.000000Z",
"updated_at": "2026-02-27T12:42:48.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view mobile logs",
"code": "MOBILE_LOGS:GET_BY_USER:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get logs by device
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/mobile-logs/device/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/mobile-logs/device/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 6,
"user_id": 286,
"device_id": 139,
"file": "/tmp/fakero5TpjO",
"date_start": "1983-04-11 10:17:59",
"date_end": "1979-02-04 03:29:59",
"created_at": "2026-02-27T12:42:48.000000Z",
"updated_at": "2026-02-27T12:42:48.000000Z"
},
{
"id": 7,
"user_id": 287,
"device_id": 140,
"file": "/tmp/fakerCRNKrJ",
"date_start": "2010-10-24 10:39:04",
"date_end": "2011-11-13 11:37:51",
"created_at": "2026-02-27T12:42:48.000000Z",
"updated_at": "2026-02-27T12:42:48.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view mobile logs",
"code": "MOBILE_LOGS:GET_BY_DEVICE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
P2P Sessions
API endpoints for managing P2P (peer-to-peer) sessions
Get active session data
requires authentication
Returns P2P sessions with status "waiting_for_decision" or "in_progress".
Example request:
curl --request GET \
--get "http://localhost:8000/api/p2p/1/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/p2p/1/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 1,
"amputee_id": null,
"device_id": null,
"clinician_id": null,
"amputee_uuid": "7974a458-0309-3103-b729-85cec9280afd",
"clinician_uuid": "a9e507f9-f6cc-3060-b258-8a048f98dbee",
"token": "R4P8T8OSFHTJ3JQ4561FJ4KYXDK7XYE1F7S0Q6J6I15BAT17KPDYYDEI83QGUKSU",
"status": "waiting_for_decision",
"created_at": "2026-02-27T12:42:33.000000Z",
"updated_at": "2026-02-27T12:42:33.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view active P2P session",
"code": "P2P_SESSIONS:GET_ACTIVE:INSUFFICIENT_PERMISSION"
}
Example response (404, Session not found):
{
"message": "P2P session not found",
"code": "P2P_SESSIONS:GET_ACTIVE:SESSION_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get session data
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/p2p/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/p2p/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 2,
"amputee_id": null,
"device_id": null,
"clinician_id": null,
"amputee_uuid": "79ce6f76-8d09-363e-9d8f-38985cb0b1e7",
"clinician_uuid": "c034cd8f-75ac-350b-a97f-15c23ebf8d83",
"token": "1KSQU3IZEE0BC9F7GIW894RQKTCSVGR283LM6TPP7G1LQ62V4M9R342AXISS1GCX",
"status": "waiting_for_decision",
"created_at": "2026-02-27T12:42:33.000000Z",
"updated_at": "2026-02-27T12:42:33.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view P2P session",
"code": "P2P_SESSIONS:GET:INSUFFICIENT_PERMISSION"
}
Example response (404, Session not found):
{
"message": "P2P session not found",
"code": "P2P_SESSIONS:GET:SESSION_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create new P2P session
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/p2p/create" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"amputee_id\": 2,
\"device_id\": 5,
\"amputee_uuid\": \"f51cf472-bf62-3b0c-a499-5c552cb1ffed\",
\"clinician_uuid\": \"3efbe46d-2a32-3c0c-9a62-1929fa379d95\"
}"
const url = new URL(
"http://localhost:8000/api/p2p/create"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"amputee_id": 2,
"device_id": 5,
"amputee_uuid": "f51cf472-bf62-3b0c-a499-5c552cb1ffed",
"clinician_uuid": "3efbe46d-2a32-3c0c-9a62-1929fa379d95"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 3,
"amputee_id": 118,
"device_id": null,
"clinician_id": 119,
"amputee_uuid": "294e4150-2e3c-3431-8fcc-3763a65d828d",
"clinician_uuid": "2b236170-13a1-35e8-98ea-aa269d777b3f",
"token": "A58YVU3IS9Q7KUFO1NZA8U090I9X3BUYHH8LCVHRUTXKVD81CLTL43GQHMOKIQZI",
"status": "waiting_for_decision",
"created_at": "2026-02-27T12:42:33.000000Z",
"updated_at": "2026-02-27T12:42:33.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create P2P session",
"code": "P2P_SESSIONS:CREATE:INSUFFICIENT_PERMISSION"
}
Example response (403, Device not assigned to patient):
{
"message": "Device is not assigned to the patient",
"code": "P2P_SESSIONS:CREATE:DEVICE_NOT_ASSIGNED"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "P2P_SESSIONS:CREATE:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update P2P session
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/p2p/1/update" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"closed\"
}"
const url = new URL(
"http://localhost:8000/api/p2p/1/update"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "closed"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 4,
"amputee_id": null,
"device_id": null,
"clinician_id": null,
"amputee_uuid": "17c7529d-2567-3c0a-aba5-ab4141022a4c",
"clinician_uuid": "2d261154-fba3-3622-a78a-63695f15b50a",
"token": "IAXBGGYCKAP6MVLH7ZYHQ8BAI7LFIQ1DTZ2BJ06D71L7INFMINTBCV90CT0IMHPQ",
"status": "waiting_for_decision",
"created_at": "2026-02-27T12:42:33.000000Z",
"updated_at": "2026-02-27T12:42:33.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update P2P session",
"code": "P2P_SESSIONS:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Session not found):
{
"message": "P2P session not found",
"code": "P2P_SESSIONS:UPDATE:SESSION_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Product features and toggles
API endpoints for product features and toggles management
Definitions:
- Product feature - part of application which can be considered as hardware compatible (with for example specific PCB version) or software compatible (with for example specific firmware version). Product features are used in versions compatibility matrix.
- Product toggle - part of application which can be enabled and disabled for current environment.
List product features
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/product/features" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/product/features"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 1,
"name": "lime",
"slug": "ut-quia-voluptatem-delectus-illum-nisi-ut-autem",
"created_at": "2026-02-27T12:42:43.000000Z",
"updated_at": "2026-02-27T12:42:43.000000Z"
},
{
"id": 2,
"name": "black",
"slug": "quae-et-autem-rerum-sint-delectus",
"created_at": "2026-02-27T12:42:43.000000Z",
"updated_at": "2026-02-27T12:42:43.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view product features and toggles",
"code": "PRODUCT_FEATURES:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create product feature
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/product/features" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Remote config\",
\"slug\": \"remote_config\"
}"
const url = new URL(
"http://localhost:8000/api/product/features"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Remote config",
"slug": "remote_config"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 3,
"name": "aqua",
"slug": "voluptas-aut-consectetur-dolorem-aut-fuga-ut-aperiam",
"created_at": "2026-02-27T12:42:43.000000Z",
"updated_at": "2026-02-27T12:42:43.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage product features and toggles",
"code": "PRODUCT_FEATURES:CREATE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update product feature
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/product/features/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Remote config\",
\"slug\": \"remote_config\"
}"
const url = new URL(
"http://localhost:8000/api/product/features/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Remote config",
"slug": "remote_config"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 4,
"name": "silver",
"slug": "voluptatem-quo-et-et-quas-et-iure",
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage product features and toggles",
"code": "PRODUCT_FEATURES:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Product feature not found):
{
"message": "Product feature not found",
"code": "PRODUCT_FEATURES:UPDATE:FEATURE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete product feature
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/product/features/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/product/features/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Product feature deleted",
"code": "PRODUCT_FEATURES:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage product features and toggles",
"code": "PRODUCT_FEATURES:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (403, Product feature belongs to compatibility entries):
{
"message": "Cannot delete: product feature belongs to existing compatibility entries (1)",
"code": "PRODUCT_FEATURES:DELETE:HAS_COMPATIBILITY_ENTRIES"
}
Example response (404, Product feature not found):
{
"message": "Product feature not found",
"code": "PRODUCT_FEATURES:DELETE:FEATURE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List product toggles
requires authentication
This endpoint returns list of global toggles. For some users there could exist user toggle which overrides these settings.
Example request:
curl --request GET \
--get "http://localhost:8000/api/product/toggles?global=1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/product/toggles"
);
const params = {
"global": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 1,
"name": "teal",
"slug": "porro-porro-sed-a-pariatur-eaque-qui-unde",
"enabled": 1,
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
},
{
"id": 2,
"name": "gray",
"slug": "voluptatem-omnis-qui-itaque-esse-dolores",
"enabled": 0,
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view product features and toggles",
"code": "PRODUCT_TOGGLES:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create product toggle
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/product/toggles" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Remote config\",
\"slug\": \"remote_config\",
\"enabled\": true
}"
const url = new URL(
"http://localhost:8000/api/product/toggles"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Remote config",
"slug": "remote_config",
"enabled": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 3,
"name": "aqua",
"slug": "tenetur-ipsa-molestiae-eum-repellendus-aliquam",
"enabled": 0,
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage product features and toggles",
"code": "PRODUCT_TOGGLES:CREATE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update product toggle
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/product/toggles/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Remote config\",
\"slug\": \"remote_config\",
\"enabled\": true
}"
const url = new URL(
"http://localhost:8000/api/product/toggles/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Remote config",
"slug": "remote_config",
"enabled": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 4,
"name": "silver",
"slug": "alias-earum-deleniti-rem-eum-necessitatibus-et-iusto-et",
"enabled": 1,
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage product features and toggles",
"code": "PRODUCT_TOGGLES:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Product toggle not found):
{
"message": "Product toggle not found",
"code": "PRODUCT_TOGGLES:UPDATE:TOGGLE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete product toggle
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/product/toggles/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/product/toggles/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Product toggle deleted",
"code": "PRODUCT_TOGGLES:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage product features and toggles",
"code": "PRODUCT_TOGGLES:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (404, Product toggle not found):
{
"message": "Product toggle not found",
"code": "PRODUCT_TOGGLES:DELETE:TOGGLE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List product FAQ
requires authentication
This endpoint returns list of product FAQ.
Example request:
curl --request GET \
--get "http://localhost:8000/api/product/faq" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/product/faq"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"question": "Soluta totam cumque expedita voluptatibus. Voluptatum et error veritatis omnis ullam. Inventore sed sed rerum et nobis tenetur qui. Atque dignissimos explicabo numquam temporibus tempore sit aliquam.",
"answer": "Et est iste est deserunt explicabo. Nostrum perferendis modi sint recusandae explicabo. Numquam qui quia architecto sed. Dolores quas delectus ut autem in occaecati modi.",
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
},
{
"id": 2,
"question": "Et voluptas tempora ducimus. Impedit eos molestiae porro vitae. Facilis odio et delectus minima et iste nihil praesentium.",
"answer": "Vero ex ut corrupti aut in. Est laboriosam quia ut veniam. Modi quo qui recusandae iure sint. Eius consequatur aspernatur occaecati et.",
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view product features and toggles",
"code": "FAQ:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List user toggles
requires authentication
This endpoint returns list of user toggles with their global toggles.
Example request:
curl --request GET \
--get "http://localhost:8000/api/user/1/toggles" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/user/1/toggles"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 1,
"toggle_id": 6,
"user_id": 251,
"enabled": 0,
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z",
"toggle": {
"id": 6,
"name": "fuchsia",
"slug": "est-velit-tempora-earum-occaecati-quas",
"enabled": 1,
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
},
{
"id": 2,
"toggle_id": 8,
"user_id": 252,
"enabled": 0,
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z",
"toggle": {
"id": 8,
"name": "aqua",
"slug": "doloremque-ut-architecto-voluptas-soluta-molestias-inventore-voluptas",
"enabled": 0,
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view product features and toggles",
"code": "USER_TOGGLES:LIST:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "USER_TOGGLES:LIST:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create user toggle
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/user/1/toggles" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"toggle_id\": 1,
\"enabled\": true
}"
const url = new URL(
"http://localhost:8000/api/user/1/toggles"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"toggle_id": 1,
"enabled": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 3,
"toggle_id": 9,
"user_id": 253,
"enabled": 0,
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage product features and toggles",
"code": "USER_TOGGLES:CREATE:INSUFFICIENT_PERMISSION"
}
Example response (403, Cannot create user toggles for SuperAdmin):
{
"message": "Cannot create user toggles for SuperAdmin",
"code": "USER_TOGGLES:CREATE:CANNOT_CREATE_FOR_SUPER_ADMIN"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "USER_TOGGLES:CREATE:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update user toggle
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/user/1/toggles/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"enabled\": true
}"
const url = new URL(
"http://localhost:8000/api/user/1/toggles/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"enabled": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 4,
"toggle_id": 10,
"user_id": 254,
"enabled": 1,
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage product features and toggles",
"code": "USER_TOGGLES:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "USER_TOGGLES:UPDATE:USER_NOT_FOUND"
}
Example response (404, User toggle not found):
{
"message": "User toggle not found",
"code": "USER_TOGGLES:UPDATE:TOGGLE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete user toggle
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/user/1/toggles/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/user/1/toggles/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "User toggle deleted",
"code": "USER_TOGGLES:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage product features and toggles",
"code": "USER_TOGGLES:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "USER_TOGGLES:DELETE:USER_NOT_FOUND"
}
Example response (404, User toggle not found):
{
"message": "User toggle not found",
"code": "USER_TOGGLES:DELETE:TOGGLE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Releases
API endpoints for releases management
List releases
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/releases" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/releases"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"version_type": "App\\Models\\SoftwareVersion",
"version_id": 14,
"description": "Doloremque asperiores deleniti mollitia adipisci consequatur est. Veritatis ut et eveniet rerum corporis provident facilis aut. Aut excepturi consectetur et enim. Omnis sed eligendi quos quidem aut.",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z",
"version": {
"id": 14,
"name": "3.3.76",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
},
{
"id": 2,
"version_type": "App\\Models\\SoftwareVersion",
"version_id": 15,
"description": "Illo voluptatibus ea debitis deleniti sequi consequatur facilis. Laboriosam illum possimus consequatur dolor ea. Laudantium est nemo adipisci laborum at. Ut iure quasi praesentium.",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z",
"version": {
"id": 15,
"name": "3.29.43",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list releases",
"code": "RELEASES:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get release
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/releases/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/releases/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 3,
"version_type": "App\\Models\\SoftwareVersion",
"version_id": 16,
"description": "Fugiat culpa veritatis sapiente incidunt adipisci natus molestiae. Quo laboriosam explicabo adipisci et. Est ut voluptas ea ipsam ullam recusandae quasi.",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z",
"version": {
"id": 16,
"name": "5.55.56",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view release",
"code": "RELEASES:GET:INSUFFICIENT_PERMISSION"
}
Example response (404, Release not found):
{
"message": "Release not found",
"code": "RELEASES:GET:RELEASE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create release
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/releases" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"version_type\": \"SoftwareVersion\",
\"version_id\": 1,
\"description\": \"This version fixes minor bugs.\"
}"
const url = new URL(
"http://localhost:8000/api/releases"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"version_type": "SoftwareVersion",
"version_id": 1,
"description": "This version fixes minor bugs."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 4,
"version_type": "App\\Models\\SoftwareVersion",
"version_id": 17,
"description": "Magni quaerat error aut aut. Omnis recusandae excepturi saepe pariatur excepturi. In facilis nam fugiat voluptas. Illum non ea dolore explicabo qui reiciendis.",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create release",
"code": "RELEASES:CREATE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update release
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/releases/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"version_type\": \"SoftwareVersion\",
\"version_id\": 1,
\"description\": \"This version fixes minor bugs.\"
}"
const url = new URL(
"http://localhost:8000/api/releases/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"version_type": "SoftwareVersion",
"version_id": 1,
"description": "This version fixes minor bugs."
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 5,
"version_type": "App\\Models\\SoftwareVersion",
"version_id": 18,
"description": "Ea iure velit dolor nisi. Exercitationem fugit dolores dignissimos dolores. Voluptatem quia expedita qui explicabo est qui voluptatem saepe. Et praesentium autem id voluptatum porro cumque.",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update release",
"code": "RELEASES:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Release not found):
{
"message": "Release not found",
"code": "RELEASES:UPDATE:RELEASE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete release
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/releases/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/releases/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Version deleted",
"code": "RELEASES:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to delete release",
"code": "RELEASES:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (404, Release not found):
{
"message": "Release not found",
"code": "RELEASES:DELETE:RELEASE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Search
API endpoints for search
Search
requires authentication
- users (by name and email)
- devices (by serial number)
Returned collection contains entries of type User or Device.
If the device has a patient assigned, this patient is included in the results as an entry of type User. If the device has no patient, the device is included in the results.
Users included in the results, but not found directly have "devices" relation filled in with the devices that match the search query.
Example request:
curl --request GET \
--get "http://localhost:8000/api/search" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"query\": \"Tom\"
}"
const url = new URL(
"http://localhost:8000/api/search"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"query": "Tom"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"type": "User",
"item": {
"id": 1,
"mrn": "MRN",
"name": "User name",
"email": "user@domain.com",
"language": "en",
"phone": "",
"phone_verified_at": null,
"address1": "",
"address2": "",
"postal_code": "",
"city": "",
"clinic_name": "Test Company",
"clinic_location": "Test Company Location",
"image": null,
"mfa_enabled": 0,
"mfa_method": "email",
"mfa_verified_to": null,
"created_by": null,
"active": 1,
"notifications_timezone": "Europe/Warsaw",
"notifications_at": "08:00:00",
"created_at": "2024-09-01T15:00:00.000000Z",
"updated_at": "2024-10-10T10:30:00.000000Z",
"invitation_status": "accepted",
"pivot": {
"assigned_user_id": 2,
"user_id": 1
},
"devices": [],
"roles": [
{
"id": 5,
"name": "Amputee",
"guard_name": "web",
"created_at": "2024-01-01T12:00:00.000000Z",
"updated_at": "2024-01-01T12:00:00.000000Z",
"pivot": {
"model_id": 1,
"role_id": 5,
"model_type": "App\\Models\\User"
}
}
]
}
},
{
"type": "Device",
"item": {
"id": 1,
"serial": "SERIAL-NUMBER",
"bluetooth_id": "BLUETOOTH_ID",
"model_id": 1,
"amputee_id": 1,
"firmware_version_id": 1,
"pcb_version_id": 1,
"active": 1,
"last_activity_at": "2024-11-11 12:00:00",
"created_at": "2024-08-30T15:00:00.000000Z",
"updated_at": "2024-09-01T16:00:00.000000Z",
"pivot": {
"user_id": 2,
"device_id": 1
}
}
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to search",
"code": "SEARCH:SEARCH:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Servicing
API endpoints for servicing
List of parts
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/servicing/parts" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/servicing/parts"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"device_model": null,
"name": "Visa",
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z"
},
{
"id": 2,
"device_model": null,
"name": "Visa",
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list service parts",
"code": "SERVICING:LIST_PARTS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Report service repair
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/servicing/repair" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "user_id=1"\
--form "device_id=1"\
--form "parts[][part_id]=1"\
--form "parts[][reason]=Mechanical issue"\
--form "files[]=@/tmp/phpuxIesb" const url = new URL(
"http://localhost:8000/api/servicing/repair"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('user_id', '1');
body.append('device_id', '1');
body.append('parts[][part_id]', '1');
body.append('parts[][reason]', 'Mechanical issue');
body.append('files[]', document.querySelector('input[name="files[]"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());Example response (201):
{
"id": 1,
"user_id": 136,
"device_id": 115,
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z",
"parts": [
{
"id": 1,
"repair_id": 1,
"part_id": 3,
"reason": "Architecto laborum repellat asperiores sint. Ut laudantium enim error et eius. In dolores quia minima sit at libero fugiat. Architecto aspernatur consequatur sint dicta.",
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z",
"part": {
"id": 3,
"device_model": null,
"name": "MasterCard",
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z"
}
},
{
"id": 2,
"repair_id": 1,
"part_id": 4,
"reason": "Quibusdam vero laborum et consequatur voluptate facere. Quas ab et est ut assumenda accusantium vel. Velit provident dolores ut sint.",
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z",
"part": {
"id": 4,
"device_model": null,
"name": "Visa",
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z"
}
},
{
"id": 3,
"repair_id": 1,
"part_id": 5,
"reason": "Vel cum cum sit occaecati. Tempora aliquid fugit quis non. Aut blanditiis dolorem aut consequuntur quod distinctio ducimus rerum.",
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z",
"part": {
"id": 5,
"device_model": null,
"name": "MasterCard",
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z"
}
}
],
"attachments": [
{
"id": 1,
"repair_id": 1,
"file": "/tmp/fakerQvc7yP",
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z"
},
{
"id": 2,
"repair_id": 1,
"file": "/tmp/faker2a4BDY",
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z"
},
{
"id": 3,
"repair_id": 1,
"file": "/tmp/faker7iuwvT",
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to report service repair",
"code": "SERVICING:REPORT_REPAIR:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Settings
API endpoints for app settings
Get app version
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/settings/app-version" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/settings/app-version"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"version": "1.6.0"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get silent push timeout
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/settings/silent-push" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/settings/silent-push"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"timeout": "15"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get available languages
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/settings/languages" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/settings/languages"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"languages": [
"de",
"en",
"es",
"it",
"pl",
"ru",
"uk"
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get mobile stores versions
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/mobile/versions" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/mobile/versions"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"ios": "1.0",
"android": "1.0"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update app version
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/settings/app-version" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"version\": \"1.6.0\"
}"
const url = new URL(
"http://localhost:8000/api/settings/app-version"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"version": "1.6.0"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"version": "1.6.0"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update settings",
"code": "SETTINGS:UPDATE_APP_VERSION:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update silent push timeout
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/settings/silent-push" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"timeout\": 15
}"
const url = new URL(
"http://localhost:8000/api/settings/silent-push"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"timeout": 15
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"timeout": "15"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update settings",
"code": "SETTINGS:UPDATE_SILENT_PUSH:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update mobile stores versions
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/mobile/versions" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"ios\": \"1.1\",
\"android\": \"1.1\"
}"
const url = new URL(
"http://localhost:8000/api/mobile/versions"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"ios": "1.1",
"android": "1.1"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"ios": "1.0",
"android": "1.0"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update settings",
"code": "SETTINGS:UPDATE_MOBILE_STORES_VERSION:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Support Ticket
API endpoints for managing support tickets
Get tickets list
requires authentication
Possible extend options:
- sender - the user who created ticket
- recipient - the user who was ticket recipient
- device - the device assigned to ticket
- messages - message allocated to ticket
- messages.attachments - list of attachments assigned to message and ticket
- messages.sender - the user who wrote the message
Example request:
curl --request GET \
--get "http://localhost:8000/api/tickets?status=new&sender=1&recipient=1&device=1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/tickets"
);
const params = {
"status": "new",
"sender": "1",
"recipient": "1",
"device": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 27,
"sender_id": 145,
"recipient_id": 146,
"device_id": 122,
"meeting_date": "2026-02-27 12:42:36",
"meeting_type": "online_meeting",
"contact_email": "gaston88@gmail.com",
"status": "new",
"created_at": "2026-02-27T12:42:36.000000Z",
"updated_at": "2026-02-27T12:42:36.000000Z",
"sender": {
"id": 145,
"mrn": "OG14NI8N1772196155",
"name": "Reina Kub I",
"email": "1772196155jaeden89@example.org",
"language": "en",
"phone": "681-390-9668",
"phone_country": "YE",
"phone_verified_at": null,
"address1": "8079 Nash Road Suite 162",
"address2": "South Alek, MN 75550",
"postal_code": "52368",
"city": "Cummerata Ltd",
"country": "LT",
"clinic_name": "Mohammadberg",
"clinic_location": "188 Rosemarie Turnpike Suite 944\nBahringerchester, IN 37858-1005",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:36.000000Z",
"updated_at": "2026-02-27T12:42:36.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"recipient": {
"id": 146,
"mrn": "GXRIVFTB1772196156",
"name": "Nash Lueilwitz",
"email": "1772196156cristian59@example.org",
"language": "en",
"phone": "+1-469-750-2480",
"phone_country": "MP",
"phone_verified_at": null,
"address1": "281 Thiel Unions Suite 002",
"address2": "Bodeside, TX 22769",
"postal_code": "51199",
"city": "D'Amore-Bosco",
"country": "ES",
"clinic_name": "Eulaliaport",
"clinic_location": "56192 Felipe Run\nSouth Jeremieton, HI 47338-2346",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:36.000000Z",
"updated_at": "2026-02-27T12:42:36.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"device": {
"id": 122,
"serial": "564ab0a6-9241-3ac9-9b5a-d30b87bb6150",
"bluetooth_id": "008d7744-cc05-33e6-9573-930ca46f30a2",
"company_id": null,
"model_id": null,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:36.000000Z",
"updated_at": "2026-02-27T12:42:36.000000Z"
},
"messages": [
{
"id": 15,
"ticket_id": 27,
"sender_id": 147,
"title": "Prof.",
"content": "Minus quisquam dolorem a qui odit.",
"is_read": false,
"created_at": "2026-02-27T12:42:36.000000Z",
"updated_at": "2026-02-27T12:42:36.000000Z"
}
]
},
{
"id": 35,
"sender_id": 159,
"recipient_id": 160,
"device_id": 123,
"meeting_date": "2026-02-27 12:42:37",
"meeting_type": "online_meeting",
"contact_email": "satterfield.graciela@hotmail.com",
"status": "new",
"created_at": "2026-02-27T12:42:37.000000Z",
"updated_at": "2026-02-27T12:42:37.000000Z",
"sender": {
"id": 159,
"mrn": "AI61FYM21772196156",
"name": "Prof. Osvaldo Tromp II",
"email": "1772196156mueller.margie@example.org",
"language": "en",
"phone": "+1-330-725-4942",
"phone_country": "MU",
"phone_verified_at": null,
"address1": "5473 O'Keefe Wells",
"address2": "West Saul, NV 12353",
"postal_code": "61358-5506",
"city": "West, Rau and Emard",
"country": "DE",
"clinic_name": "East Jonathon",
"clinic_location": "247 Ankunding Island\nKevenmouth, HI 89774",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:37.000000Z",
"updated_at": "2026-02-27T12:42:37.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"recipient": {
"id": 160,
"mrn": "1NBX8ZAA1772196157",
"name": "Sylvia McLaughlin",
"email": "1772196157santino.mitchell@example.com",
"language": "en",
"phone": "930-740-1327",
"phone_country": "SE",
"phone_verified_at": null,
"address1": "55049 Ryan Keys",
"address2": "Bashirianside, CA 18863",
"postal_code": "77626-5472",
"city": "Block LLC",
"country": "RO",
"clinic_name": "South Georgianaport",
"clinic_location": "8649 Jarred Keys\nStrackeburgh, UT 75602",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:37.000000Z",
"updated_at": "2026-02-27T12:42:37.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"device": {
"id": 123,
"serial": "1af29292-74a2-3a46-97c7-bc719acc67cc",
"bluetooth_id": "ef504148-cf2b-3f11-960a-ad4fd1acb066",
"company_id": null,
"model_id": null,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:37.000000Z",
"updated_at": "2026-02-27T12:42:37.000000Z"
},
"messages": [
{
"id": 19,
"ticket_id": 35,
"sender_id": 161,
"title": "Prof.",
"content": "Et dolorem consequuntur doloremque veniam et aut.",
"is_read": false,
"created_at": "2026-02-27T12:42:37.000000Z",
"updated_at": "2026-02-27T12:42:37.000000Z"
}
]
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list support tickets",
"code": "TICKETS:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get tickets status
requires authentication
Counts tickets by their status
Example request:
curl --request GET \
--get "http://localhost:8000/api/tickets/status" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/tickets/status"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"unread": 1
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list support tickets",
"code": "TICKETS:STATUS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get support ticket
requires authentication
Returns single support ticket in the response.
Example request:
curl --request GET \
--get "http://localhost:8000/api/ticket/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/ticket/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 43,
"sender_id": 173,
"recipient_id": 174,
"device_id": 124,
"meeting_date": "2026-02-27 12:42:38",
"meeting_type": "online_meeting",
"contact_email": "jackson.mckenzie@doyle.com",
"status": "new",
"created_at": "2026-02-27T12:42:38.000000Z",
"updated_at": "2026-02-27T12:42:38.000000Z",
"sender": {
"id": 173,
"mrn": "V3LOY7A51772196158",
"name": "Heidi Willms",
"email": "1772196158denesik.arlie@example.org",
"language": "en",
"phone": "+1 (941) 913-7036",
"phone_country": "CD",
"phone_verified_at": null,
"address1": "5637 Goodwin Turnpike Apt. 003",
"address2": "Abelborough, IN 65298-4783",
"postal_code": "01257",
"city": "Cummerata-Gutmann",
"country": "PL",
"clinic_name": "Dareland",
"clinic_location": "107 Delbert Lake\nLittleport, IN 42662",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:38.000000Z",
"updated_at": "2026-02-27T12:42:38.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"recipient": {
"id": 174,
"mrn": "ESKUGD411772196158",
"name": "Toby Gottlieb V",
"email": "1772196158aletha96@example.org",
"language": "en",
"phone": "+1-737-574-5213",
"phone_country": "IE",
"phone_verified_at": null,
"address1": "3539 Stanton Green Apt. 856",
"address2": "East Lorenzberg, IN 54456-3196",
"postal_code": "91312",
"city": "Skiles, Metz and Torphy",
"country": "DK",
"clinic_name": "Haaghaven",
"clinic_location": "629 Gislason Brooks\nEast Narcisomouth, NJ 00800-7407",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:38.000000Z",
"updated_at": "2026-02-27T12:42:38.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"device": {
"id": 124,
"serial": "e7e73b53-0b5d-3340-80dc-ece13ebd0102",
"bluetooth_id": "4ba6923f-6514-32fa-b078-63c44ff178b9",
"company_id": null,
"model_id": null,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:38.000000Z",
"updated_at": "2026-02-27T12:42:38.000000Z"
},
"messages": [
{
"id": 23,
"ticket_id": 43,
"sender_id": 175,
"title": "Dr.",
"content": "Iure est vitae atque delectus eum delectus.",
"is_read": false,
"created_at": "2026-02-27T12:42:38.000000Z",
"updated_at": "2026-02-27T12:42:38.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view support ticket",
"code": "TICKETS:GET:INSUFFICIENT_PERMISSION"
}
Example response (404, Support ticket not found):
{
"message": "Support ticket not found",
"code": "TICKETS:GET:TICKET_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get support ticket history
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/ticket/1/history" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/ticket/1/history"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"ticket_id": 51,
"author_id": 188,
"action": "optio",
"reason": "Labore ratione perferendis occaecati qui ut cupiditate voluptas.",
"created_at": "2026-02-27T12:42:39.000000Z",
"updated_at": "2026-02-27T12:42:39.000000Z"
},
{
"id": 2,
"ticket_id": 52,
"author_id": 190,
"action": "praesentium",
"reason": "Eius a nihil magnam sit et aut consequatur.",
"created_at": "2026-02-27T12:42:39.000000Z",
"updated_at": "2026-02-27T12:42:39.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view support ticket",
"code": "TICKETS:HISTORY:INSUFFICIENT_PERMISSION"
}
Example response (404, Support ticket not found):
{
"message": "Support ticket not found",
"code": "TICKETS:HISTORY:TICKET_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get support ticket available filters
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/tickets/available-filters" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/tickets/available-filters"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
{
"clinicians": [
{
"id": 95,
"mrn": null,
"name": "Name",
"email": "email",
"region": "us",
"language": "pl",
"phone": "+48-555555555",
"phone_verified_at": null,
"address1": "Address",
"address2": "Address 2",
"postal_code": "",
"city": "",
"clinic_name": "Name",
"clinic_location": "Name",
"image": "https://aether-dev-bucket.s3.amazonaws.com/users/LDueuv1uG218G7owaiLAaWRkpaGxjB0jEFwzZsT1.png",
"mfa_enabled": 0,
"mfa_method": "sms",
"mfa_verified_to": null,
"location_id": 2,
"created_by": 1,
"active": 1,
"notifications_timezone": "America/Adak",
"notifications_at": null,
"created_at": "2022-07-19T14:43:37.000000Z",
"updated_at": "2024-09-27T05:52:51.000000Z",
"invitation_status": "expired",
"roles": [
{
"id": 2,
"name": "Clinician",
"guard_name": "web",
"created_at": "2022-03-21T17:15:47.000000Z",
"updated_at": "2022-03-21T17:15:47.000000Z",
"pivot": {
"model_id": 95,
"role_id": 2,
"model_type": "App\\Models\\User"
}
}
]
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create support ticket",
"code": "TICKETS:AVAILABLE_FILTERS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create new support ticket
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/tickets" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "recipient=1"\
--form "device=1"\
--form "meeting_type=online_meeting"\
--form "meeting_date=2026-02-27 12:42:39"\
--form "contact_email=robbie68@tremblay.com"\
--form "message[content]=Sunt provident qui alias."\
--form "message[title]=Corrupti eum quia dolor."\
--form "message[attachments][]=@/tmp/phpwFHw9J" const url = new URL(
"http://localhost:8000/api/tickets"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('recipient', '1');
body.append('device', '1');
body.append('meeting_type', 'online_meeting');
body.append('meeting_date', '2026-02-27 12:42:39');
body.append('contact_email', 'robbie68@tremblay.com');
body.append('message[content]', 'Sunt provident qui alias.');
body.append('message[title]', 'Corrupti eum quia dolor.');
body.append('message[attachments][]', document.querySelector('input[name="message[attachments][]"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());Example response (201):
{
"id": 53,
"sender_id": 191,
"recipient_id": 192,
"device_id": 125,
"meeting_date": "2026-02-27 12:42:39",
"meeting_type": "online_meeting",
"contact_email": "tbeer@hotmail.com",
"status": "new",
"created_at": "2026-02-27T12:42:39.000000Z",
"updated_at": "2026-02-27T12:42:39.000000Z",
"sender": {
"id": 191,
"mrn": "3O4B1VPA1772196159",
"name": "Jarod Cummerata",
"email": "1772196159abdullah45@example.net",
"language": "en",
"phone": "820.263.2296",
"phone_country": "SZ",
"phone_verified_at": null,
"address1": "9344 Ludwig Field Apt. 932",
"address2": "Demondmouth, AK 42200-0027",
"postal_code": "40969",
"city": "Hill-Jerde",
"country": "RO",
"clinic_name": "North Timmothytown",
"clinic_location": "114 Nickolas Key\nClaudiechester, MT 67070",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:39.000000Z",
"updated_at": "2026-02-27T12:42:39.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"recipient": {
"id": 192,
"mrn": "MD7GPFB71772196159",
"name": "Amani Rippin",
"email": "1772196159lehner.alvah@example.org",
"language": "en",
"phone": "+1.984.673.8528",
"phone_country": "KI",
"phone_verified_at": null,
"address1": "33804 Judy Inlet Apt. 703",
"address2": "Kennyton, WV 38478-9785",
"postal_code": "38154-9514",
"city": "Leannon, Krajcik and Graham",
"country": "BE",
"clinic_name": "Dominiqueton",
"clinic_location": "7641 Cassin Grove Apt. 536\nSouth Jade, MS 23585-1404",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:39.000000Z",
"updated_at": "2026-02-27T12:42:39.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"device": {
"id": 125,
"serial": "bc5c261b-04a4-3093-bc03-4755a6fefc1b",
"bluetooth_id": "166d06b2-a422-383d-a8c6-6380e90780d7",
"company_id": null,
"model_id": null,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:39.000000Z",
"updated_at": "2026-02-27T12:42:39.000000Z"
},
"messages": [
{
"id": 27,
"ticket_id": 53,
"sender_id": 193,
"title": "Prof.",
"content": "Blanditiis expedita reprehenderit minima rerum temporibus.",
"is_read": false,
"created_at": "2026-02-27T12:42:39.000000Z",
"updated_at": "2026-02-27T12:42:39.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create support ticket",
"code": "TICKETS:CREATE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Close support ticket
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/ticket/1/close" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/ticket/1/close"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (202):
{
"id": 61,
"sender_id": 205,
"recipient_id": 206,
"device_id": 126,
"meeting_date": "2026-02-27 12:42:40",
"meeting_type": "online_meeting",
"contact_email": "kian.marquardt@yahoo.com",
"status": "new",
"created_at": "2026-02-27T12:42:40.000000Z",
"updated_at": "2026-02-27T12:42:40.000000Z",
"sender": {
"id": 205,
"mrn": "JNKWOINP1772196160",
"name": "Mathias McDermott",
"email": "1772196160oda.mcglynn@example.net",
"language": "en",
"phone": "225-946-1718",
"phone_country": "PS",
"phone_verified_at": null,
"address1": "107 Metz Park Suite 466",
"address2": "Raleighburgh, RI 70349-3262",
"postal_code": "29125",
"city": "Romaguera LLC",
"country": "FI",
"clinic_name": "Wiegandburgh",
"clinic_location": "104 Bettye Loop Suite 529\nPollichmouth, MI 85977",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:40.000000Z",
"updated_at": "2026-02-27T12:42:40.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"recipient": {
"id": 206,
"mrn": "4TEU0JQO1772196160",
"name": "Brandy Lehner DVM",
"email": "1772196160herbert.bernier@example.org",
"language": "en",
"phone": "283-932-1903",
"phone_country": "JM",
"phone_verified_at": null,
"address1": "36345 Donnie Harbors Apt. 694",
"address2": "South Berniceville, SD 27202",
"postal_code": "57521-2675",
"city": "Halvorson and Sons",
"country": "IE",
"clinic_name": "East Alanna",
"clinic_location": "64034 Alisa Trafficway Suite 126\nWest Benny, DC 67251-5989",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:40.000000Z",
"updated_at": "2026-02-27T12:42:40.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"device": {
"id": 126,
"serial": "df7bf68d-fe79-3781-8d23-82386c788177",
"bluetooth_id": "195a2d33-7594-3e42-b2e5-fdb9424984e0",
"company_id": null,
"model_id": null,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:40.000000Z",
"updated_at": "2026-02-27T12:42:40.000000Z"
},
"messages": []
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to close support ticket",
"code": "TICKETS:CLOSE:INSUFFICIENT_PERMISSION"
}
Example response (404, Support ticket not found):
{
"message": "Support ticket not found",
"code": "TICKETS:CLOSE:TICKET_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reopen support ticket
requires authentication
Patient (Amputee) role can reopen only non-config tickets.
For config tickets patients will get "Insufficient permission" response.
For patients role reason field is required.
Example request:
curl --request POST \
"http://localhost:8000/api/ticket/1/reopen" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Something is still not working\"
}"
const url = new URL(
"http://localhost:8000/api/ticket/1/reopen"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Something is still not working"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 3,
"ticket_id": 62,
"author_id": 208,
"action": "minima",
"reason": "Culpa architecto corporis sed commodi.",
"created_at": "2026-02-27T12:42:40.000000Z",
"updated_at": "2026-02-27T12:42:40.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to reopen support ticket",
"code": "TICKETS:REOPEN:INSUFFICIENT_PERMISSION"
}
Example response (404, Support ticket not found):
{
"message": "Support ticket not found",
"code": "TICKETS:REOPEN:TICKET_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create new support ticket message
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/ticket/1/messages" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "title=Dolore dolorem laborum."\
--form "content=Unde fugiat amet quis in nostrum quas dolor tempore."\
--form "attachments[]=@/tmp/phpWvXaHB" const url = new URL(
"http://localhost:8000/api/ticket/1/messages"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('title', 'Dolore dolorem laborum.');
body.append('content', 'Unde fugiat amet quis in nostrum quas dolor tempore.');
body.append('attachments[]', document.querySelector('input[name="attachments[]"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());Example response (201):
{
"id": 63,
"sender_id": 209,
"recipient_id": 210,
"device_id": 127,
"meeting_date": "2026-02-27 12:42:40",
"meeting_type": "online_meeting",
"contact_email": "blanche02@yahoo.com",
"status": "new",
"created_at": "2026-02-27T12:42:41.000000Z",
"updated_at": "2026-02-27T12:42:41.000000Z",
"sender": {
"id": 209,
"mrn": "TK1EPMNZ1772196160",
"name": "Maci Murazik",
"email": "1772196160catherine10@example.net",
"language": "en",
"phone": "1-929-419-3298",
"phone_country": "CI",
"phone_verified_at": null,
"address1": "812 Bud Locks",
"address2": "North London, TX 22675-1300",
"postal_code": "94046",
"city": "Cormier, Haag and Kemmer",
"country": "BE",
"clinic_name": "East Darrionfurt",
"clinic_location": "2744 Klocko Roads\nEzekielville, MO 11706-6357",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:40.000000Z",
"updated_at": "2026-02-27T12:42:40.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"recipient": {
"id": 210,
"mrn": "WOWEZ7VL1772196160",
"name": "Jakayla Davis",
"email": "1772196160judson.dooley@example.org",
"language": "en",
"phone": "1-828-946-2699",
"phone_country": "VU",
"phone_verified_at": null,
"address1": "3536 Renner Islands",
"address2": "Krajcikchester, ID 94329",
"postal_code": "12460-9927",
"city": "Simonis, Collins and Miller",
"country": "FI",
"clinic_name": "Daneshire",
"clinic_location": "61389 Yost Prairie\nPort Loniefort, AK 69694",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:41.000000Z",
"updated_at": "2026-02-27T12:42:41.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"device": {
"id": 127,
"serial": "544b4e00-9bc2-3d8a-8a4c-173cccbeef46",
"bluetooth_id": "c8c797db-c406-3c3f-a171-a41b5865d373",
"company_id": null,
"model_id": null,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:41.000000Z",
"updated_at": "2026-02-27T12:42:41.000000Z"
},
"messages": [
{
"id": 31,
"ticket_id": 63,
"sender_id": 211,
"title": "Prof.",
"content": "Praesentium recusandae omnis eveniet atque eos laboriosam labore dolor.",
"is_read": false,
"created_at": "2026-02-27T12:42:41.000000Z",
"updated_at": "2026-02-27T12:42:41.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create support ticket",
"code": "TICKETS:CREATE_MESSAGE:INSUFFICIENT_PERMISSION"
}
Example response (404, Support ticket not found):
{
"message": "Support ticket not found",
"code": "TICKETS:CREATE_MESSAGE:TICKET_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mark all messages as read
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/ticket/1/read" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/ticket/1/read"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (202):
{
"id": 71,
"sender_id": 223,
"recipient_id": 224,
"device_id": 128,
"meeting_date": "2026-02-27 12:42:41",
"meeting_type": "online_meeting",
"contact_email": "upton.emory@yahoo.com",
"status": "new",
"created_at": "2026-02-27T12:42:42.000000Z",
"updated_at": "2026-02-27T12:42:42.000000Z",
"sender": {
"id": 223,
"mrn": "M48WMPBP1772196161",
"name": "Mrs. Hettie Feil",
"email": "1772196161dfay@example.net",
"language": "en",
"phone": "754.850.2731",
"phone_country": "GG",
"phone_verified_at": null,
"address1": "908 Greenholt Ranch Suite 270",
"address2": "Bernierview, WA 40492",
"postal_code": "78083",
"city": "Mraz-Hand",
"country": "GR",
"clinic_name": "Deloresburgh",
"clinic_location": "3160 Newell Well\nSouth Theoside, NE 20888",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:41.000000Z",
"updated_at": "2026-02-27T12:42:41.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"recipient": {
"id": 224,
"mrn": "KSG1LKQI1772196161",
"name": "Berry Rohan V",
"email": "1772196161lenny.bahringer@example.com",
"language": "en",
"phone": "(562) 716-3844",
"phone_country": "NU",
"phone_verified_at": null,
"address1": "7102 Abernathy Harbor Apt. 940",
"address2": "Keelingberg, ND 78123-9148",
"postal_code": "12312-2978",
"city": "Casper PLC",
"country": "IT",
"clinic_name": "New Dolly",
"clinic_location": "88766 Erwin Forge\nEast Jeanette, IL 70203",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:42.000000Z",
"updated_at": "2026-02-27T12:42:42.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"device": {
"id": 128,
"serial": "97afb1e9-9c36-3581-bcc3-202dd54e2338",
"bluetooth_id": "8528e403-0c26-3b5b-adaf-6e2f3b0f4b47",
"company_id": null,
"model_id": null,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:42.000000Z",
"updated_at": "2026-02-27T12:42:42.000000Z"
},
"messages": [
{
"id": 35,
"ticket_id": 71,
"sender_id": 225,
"title": "Mr.",
"content": "Enim qui quibusdam natus libero.",
"is_read": false,
"created_at": "2026-02-27T12:42:42.000000Z",
"updated_at": "2026-02-27T12:42:42.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to read message",
"code": "TICKETS:READ_ALL:INSUFFICIENT_PERMISSION"
}
Example response (404, Support ticket not found):
{
"message": "Support ticket not found",
"code": "TICKETS:READ_ALL:TICKET_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mark single message as read
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/ticket/1/read/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/ticket/1/read/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (202):
{
"id": 79,
"sender_id": 237,
"recipient_id": 238,
"device_id": 129,
"meeting_date": "2026-02-27 12:42:42",
"meeting_type": "online_meeting",
"contact_email": "jovan03@gmail.com",
"status": "new",
"created_at": "2026-02-27T12:42:43.000000Z",
"updated_at": "2026-02-27T12:42:43.000000Z",
"sender": {
"id": 237,
"mrn": "Y7X87C2L1772196162",
"name": "Lennie Gleason",
"email": "1772196162casandra.gutkowski@example.org",
"language": "en",
"phone": "843-994-0502",
"phone_country": "NF",
"phone_verified_at": null,
"address1": "152 Kamille Avenue Apt. 401",
"address2": "Nolanfurt, MS 90002",
"postal_code": "87030-0315",
"city": "Labadie Group",
"country": "SE",
"clinic_name": "Duncanshire",
"clinic_location": "693 Estel Summit\nSwaniawskiton, AL 78048-8694",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:42.000000Z",
"updated_at": "2026-02-27T12:42:42.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"recipient": {
"id": 238,
"mrn": "D9APNZYN1772196162",
"name": "Maritza Fisher I",
"email": "1772196162turcotte.zoey@example.net",
"language": "en",
"phone": "830.893.6523",
"phone_country": "AD",
"phone_verified_at": null,
"address1": "75946 Larkin Station",
"address2": "West Almouth, NC 53248",
"postal_code": "15388",
"city": "Shields LLC",
"country": "CZ",
"clinic_name": "Keonburgh",
"clinic_location": "4912 Corwin Harbor Suite 708\nNew Ottisland, LA 13207",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:43.000000Z",
"updated_at": "2026-02-27T12:42:43.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": []
},
"device": {
"id": 129,
"serial": "376670a6-7394-3b27-8db6-2b5875c6ca72",
"bluetooth_id": "2824b693-e249-3d80-a00c-3d2b57758232",
"company_id": null,
"model_id": null,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:43.000000Z",
"updated_at": "2026-02-27T12:42:43.000000Z"
},
"messages": [
{
"id": 39,
"ticket_id": 79,
"sender_id": 239,
"title": "Mr.",
"content": "Cupiditate distinctio est sit repudiandae.",
"is_read": false,
"created_at": "2026-02-27T12:42:43.000000Z",
"updated_at": "2026-02-27T12:42:43.000000Z"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to read message",
"code": "TICKETS:READ_MESSAGE:INSUFFICIENT_PERMISSION"
}
Example response (404, Message not found):
{
"message": "Message not found",
"code": "TICKETS:READ_MESSAGE:MESSAGE_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Tooltips
API endpoints for managing tooltips
List tooltips
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/tooltips" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/tooltips"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"name": "Forrest Smitham",
"type": "video",
"language": "mh",
"file": "0",
"created_by": 301,
"created_at": "2026-02-27T12:42:50.000000Z",
"updated_at": "2026-02-27T12:42:50.000000Z",
"deleted_at": null
},
{
"id": 2,
"name": "Prof. Elenor Kihn DDS",
"type": "video",
"language": "af",
"file": "0",
"created_by": 302,
"created_at": "2026-02-27T12:42:50.000000Z",
"updated_at": "2026-02-27T12:42:50.000000Z",
"deleted_at": null
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list tooltips",
"code": "TOOLTIPS:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List archived tooltips
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/tooltips/archive" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/tooltips/archive"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 3,
"name": "Bernadine Lowe",
"type": "video",
"language": "nn",
"file": "0",
"created_by": 303,
"created_at": "2026-02-27T12:42:50.000000Z",
"updated_at": "2026-02-27T12:42:50.000000Z",
"deleted_at": null
},
{
"id": 4,
"name": "Kirk Stehr III",
"type": "image",
"language": "ik",
"file": "0",
"created_by": 304,
"created_at": "2026-02-27T12:42:50.000000Z",
"updated_at": "2026-02-27T12:42:50.000000Z",
"deleted_at": null
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage tooltips",
"code": "TOOLTIPS:LIST_ARCHIVE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create new tooltip
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/tooltips" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "name=Verla Avenue"\
--form "type=image"\
--form "language=kl"\
--form "file=@/tmp/php8AI6Tl" const url = new URL(
"http://localhost:8000/api/tooltips"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('name', 'Verla Avenue');
body.append('type', 'image');
body.append('language', 'kl');
body.append('file', document.querySelector('input[name="file"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());Example response (201):
{
"id": 5,
"name": "Cleta Dare",
"type": "image",
"language": "bh",
"file": "0",
"created_by": 305,
"created_at": "2026-02-27T12:42:50.000000Z",
"updated_at": "2026-02-27T12:42:50.000000Z",
"deleted_at": null
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage tooltips",
"code": "TOOLTIPS:CREATE:INSUFFICIENT_PERMISSION"
}
Example response (500, Server error):
{
"message": "Server error: tooltip not created",
"code": "TOOLTIPS:CREATE:SERVER_ERROR"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Archive tooltip
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/tooltips/1/archive" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/tooltips/1/archive"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Tooltip archived",
"code": "TOOLTIPS:ARCHIVE:ARCHIVED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage tooltips",
"code": "TOOLTIPS:ARCHIVE:INSUFFICIENT_PERMISSION"
}
Example response (404, Tooltip not found):
{
"message": "Tooltip not found",
"code": "TOOLTIPS:ARCHIVE:TOOLTIP_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Restore archived tooltip
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/tooltips/1/restore" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/tooltips/1/restore"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Tooltip restored",
"code": "TOOLTIPS:RESTORE:RESTORED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage tooltips",
"code": "TOOLTIPS:RESTORE:INSUFFICIENT_PERMISSION"
}
Example response (404, Tooltip not found):
{
"message": "Tooltip not found",
"code": "TOOLTIPS:RESTORE:TOOLTIP_NOT_FOUND"
}
Example response (404, Tooltip is not archived):
{
"message": "Tooltip is not archived",
"code": "TOOLTIPS:RESTORE:TOOLTIP_NOT_ARCHIVED"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Trainings
API endpoints for trainings
Get user trainings
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/trainings" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/trainings"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 1,
"user_id": 309,
"training_id": 2,
"notifications_enabled": 1,
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z",
"training": {
"id": 2,
"name": "non voluptatem",
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z"
}
},
{
"id": 2,
"user_id": 310,
"training_id": 4,
"notifications_enabled": 1,
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z",
"training": {
"id": 4,
"name": "corrupti magni",
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z"
}
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage user trainings",
"code": "TRAININGS:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get trainings for specific user (clinician access)
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/trainings/user/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/trainings/user/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 3,
"user_id": 311,
"training_id": 6,
"notifications_enabled": 1,
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z",
"training": {
"id": 6,
"name": "cum deleniti",
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z"
}
},
{
"id": 4,
"user_id": 312,
"training_id": 8,
"notifications_enabled": 1,
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z",
"training": {
"id": 8,
"name": "fugiat dolorum",
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z"
}
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to access patient training",
"code": "TRAININGS:LIST:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "TRAININGS:LIST:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get user badges
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/trainings/1/user-badges" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/trainings/1/user-badges"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 1,
"user_id": 313,
"badge_id": 1,
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z"
},
{
"id": 2,
"user_id": 314,
"badge_id": 2,
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage user trainings",
"code": "TRAININGS:BADGES:INSUFFICIENT_PERMISSION"
}
Example response (403, User has no training started):
{
"message": "User has no training started",
"code": "TRAININGS:BADGES:NO_USER_TRAINING"
}
Example response (404, Training not found):
{
"message": "Training not found",
"code": "TRAININGS:BADGES:TRAINING_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Start user training
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/trainings/start/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/trainings/start/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (201):
{
"id": 5,
"user_id": 315,
"training_id": 9,
"notifications_enabled": 1,
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage user trainings",
"code": "TRAININGS:START:INSUFFICIENT_PERMISSION"
}
Example response (403, User training already started):
{
"message": "Cannot start: training already started",
"code": "TRAININGS:START:ALREADY_STARTED"
}
Example response (404, Training not found):
{
"message": "Training not found",
"code": "TRAININGS:START:TRAINING_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update training
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/trainings/update/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"notifications_enabled\": false
}"
const url = new URL(
"http://localhost:8000/api/trainings/update/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"notifications_enabled": false
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"id": 6,
"user_id": 316,
"training_id": 10,
"notifications_enabled": 1,
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage user trainings",
"code": "TRAININGS:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (403, User has no training started):
{
"message": "User has no training started",
"code": "TRAININGS:UPDATE:NO_USER_TRAINING"
}
Example response (404, Training not found):
{
"message": "Training not found",
"code": "TRAININGS:UPDATE:TRAINING_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get training progress
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/trainings/progress/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/trainings/progress/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 7,
"user_id": 317,
"training_id": 11,
"notifications_enabled": 1,
"created_at": "2026-02-27T12:42:51.000000Z",
"updated_at": "2026-02-27T12:42:51.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage user trainings",
"code": "TRAININGS:PROGRESS:INSUFFICIENT_PERMISSION"
}
Example response (403, User has no training started):
{
"message": "User has no training started",
"code": "TRAININGS:PROGRESS:NO_USER_TRAINING"
}
Example response (404, Training not found):
{
"message": "Training not found",
"code": "TRAININGS:PROGRESS:TRAINING_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mark training task done
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/trainings/1/day/2/task/3" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/trainings/1/day/2/task/3"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200):
{
"id": 8,
"user_id": 318,
"training_id": 12,
"notifications_enabled": 1,
"created_at": "2026-02-27T12:42:52.000000Z",
"updated_at": "2026-02-27T12:42:52.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage user trainings",
"code": "TRAININGS:MARK_DONE:INSUFFICIENT_PERMISSION"
}
Example response (403, User has no training started):
{
"message": "User has no training started",
"code": "TRAININGS:MARK_DONE:NO_USER_TRAINING"
}
Example response (404, Training not found):
{
"message": "Training not found",
"code": "TRAININGS:MARK_DONE:TRAINING_NOT_FOUND"
}
Example response (404, Training day not found):
{
"message": "Training day not found",
"code": "TRAININGS:MARK_DONE:TRAINING_DAY_NOT_FOUND"
}
Example response (404, Training task not found):
{
"message": "Training task not found",
"code": "TRAININGS:MARK_DONE:TRAINING_TASK_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Save training exercises attempts
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/trainings/1/day/2/task/3/attempts" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "exercises[][date_start]=2025-09-19 14:18:05"\
--form "exercises[][date_end]=2015-03-27 11:00:15"\
--form "exercises[][end_reason]=success"\
--form "exercises[][config][common][fingerStrength][]=1"\
--form "exercises[][config][common][gripPositions][_]=0"\
--form "exercises[][config][common][gripPositions][0][initial][]=19"\
--form "exercises[][config][common][gripPositions][0][limit][]=49"\
--form "exercises[][config][common][gripPositions][1][initial][]=9"\
--form "exercises[][config][common][gripPositions][1][limit][]=71"\
--form "exercises[][config][common][gripPositions][2][initial][]=76"\
--form "exercises[][config][common][gripPositions][2][limit][]=79"\
--form "exercises[][config][common][gripPositions][3][initial][]=35"\
--form "exercises[][config][common][gripPositions][3][limit][]=88"\
--form "exercises[][config][common][gripPositions][4][initial][]=19"\
--form "exercises[][config][common][gripPositions][4][limit][]=21"\
--form "exercises[][config][common][gripPositions][5][initial][]=2"\
--form "exercises[][config][common][gripPositions][5][limit][]=70"\
--form "exercises[][config][common][gripPositions][6][initial][]=10"\
--form "exercises[][config][common][gripPositions][6][limit][]=61"\
--form "exercises[][config][common][gripPositions][7][initial][]=4"\
--form "exercises[][config][common][gripPositions][7][limit][]=69"\
--form "exercises[][config][common][gripPositions][8][initial][]=27"\
--form "exercises[][config][common][gripPositions][8][limit][]=60"\
--form "exercises[][config][common][gripPositions][9][initial][]=25"\
--form "exercises[][config][common][gripPositions][9][limit][]=92"\
--form "exercises[][config][common][gripPositions][10][initial][]=45"\
--form "exercises[][config][common][gripPositions][10][limit][]=49"\
--form "exercises[][config][common][gripPositions][11][initial][]=19"\
--form "exercises[][config][common][gripPositions][11][limit][]=39"\
--form "exercises[][config][common][gripPositions][12][initial][]=63"\
--form "exercises[][config][common][gripPositions][12][limit][]=67"\
--form "exercises[][config][common][gripPositions][13][initial][]=43"\
--form "exercises[][config][common][gripPositions][13][limit][]=67"\
--form "exercises[][config][common][inputSite][]=1"\
--form "exercises[][config][modes][][id]=83"\
--form "exercises[][config][modes][][name]=Aut blanditiis exercitationem voluptatem aut."\
--form "exercises[][config][modes][][slot]=0"\
--form "exercises[][config][modes][][config][autoGrasp][]=0"\
--form "exercises[][config][modes][][config][coContractionTimings][]=500"\
--form "exercises[][config][modes][][config][controlMode][]=0"\
--form "exercises[][config][modes][][config][emgGains][]=100"\
--form "exercises[][config][modes][][config][emgSpike][]=0"\
--form "exercises[][config][modes][][config][emgThresholds][]=90"\
--form "exercises[][config][modes][][config][gripPairsConfig][]=8"\
--form "exercises[][config][modes][][config][gripSequentialConfig][]=255"\
--form "exercises[][config][modes][][config][gripSwitchingMode][]=2"\
--form "exercises[][config][modes][][config][holdOpen][]=2000"\
--form "exercises[][config][modes][][config][pulseTimings][]=240"\
--form "exercises[][config][modes][][config][softGrip][]=1"\
--form "exercises[][config][modes][][config][speedControlStrategy][]=0"\
--form "exercises[][firmware_id]=21066896"\
--form "exercises[][app_version]=9.52.47"\
--form "exercises[][attempts][][date_start]=2004-05-21 07:49:56"\
--form "exercises[][attempts][][date_end]=1985-04-30 05:54:35"\
--form "exercises[][attempts][][result]=success"\
--form "exercises[][emg_file]=@/tmp/phpth9DZ3" const url = new URL(
"http://localhost:8000/api/trainings/1/day/2/task/3/attempts"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('exercises[][date_start]', '2025-09-19 14:18:05');
body.append('exercises[][date_end]', '2015-03-27 11:00:15');
body.append('exercises[][end_reason]', 'success');
body.append('exercises[][config][common][fingerStrength][]', '1');
body.append('exercises[][config][common][gripPositions][_]', '0');
body.append('exercises[][config][common][gripPositions][0][initial][]', '19');
body.append('exercises[][config][common][gripPositions][0][limit][]', '49');
body.append('exercises[][config][common][gripPositions][1][initial][]', '9');
body.append('exercises[][config][common][gripPositions][1][limit][]', '71');
body.append('exercises[][config][common][gripPositions][2][initial][]', '76');
body.append('exercises[][config][common][gripPositions][2][limit][]', '79');
body.append('exercises[][config][common][gripPositions][3][initial][]', '35');
body.append('exercises[][config][common][gripPositions][3][limit][]', '88');
body.append('exercises[][config][common][gripPositions][4][initial][]', '19');
body.append('exercises[][config][common][gripPositions][4][limit][]', '21');
body.append('exercises[][config][common][gripPositions][5][initial][]', '2');
body.append('exercises[][config][common][gripPositions][5][limit][]', '70');
body.append('exercises[][config][common][gripPositions][6][initial][]', '10');
body.append('exercises[][config][common][gripPositions][6][limit][]', '61');
body.append('exercises[][config][common][gripPositions][7][initial][]', '4');
body.append('exercises[][config][common][gripPositions][7][limit][]', '69');
body.append('exercises[][config][common][gripPositions][8][initial][]', '27');
body.append('exercises[][config][common][gripPositions][8][limit][]', '60');
body.append('exercises[][config][common][gripPositions][9][initial][]', '25');
body.append('exercises[][config][common][gripPositions][9][limit][]', '92');
body.append('exercises[][config][common][gripPositions][10][initial][]', '45');
body.append('exercises[][config][common][gripPositions][10][limit][]', '49');
body.append('exercises[][config][common][gripPositions][11][initial][]', '19');
body.append('exercises[][config][common][gripPositions][11][limit][]', '39');
body.append('exercises[][config][common][gripPositions][12][initial][]', '63');
body.append('exercises[][config][common][gripPositions][12][limit][]', '67');
body.append('exercises[][config][common][gripPositions][13][initial][]', '43');
body.append('exercises[][config][common][gripPositions][13][limit][]', '67');
body.append('exercises[][config][common][inputSite][]', '1');
body.append('exercises[][config][modes][][id]', '83');
body.append('exercises[][config][modes][][name]', 'Aut blanditiis exercitationem voluptatem aut.');
body.append('exercises[][config][modes][][slot]', '0');
body.append('exercises[][config][modes][][config][autoGrasp][]', '0');
body.append('exercises[][config][modes][][config][coContractionTimings][]', '500');
body.append('exercises[][config][modes][][config][controlMode][]', '0');
body.append('exercises[][config][modes][][config][emgGains][]', '100');
body.append('exercises[][config][modes][][config][emgSpike][]', '0');
body.append('exercises[][config][modes][][config][emgThresholds][]', '90');
body.append('exercises[][config][modes][][config][gripPairsConfig][]', '8');
body.append('exercises[][config][modes][][config][gripSequentialConfig][]', '255');
body.append('exercises[][config][modes][][config][gripSwitchingMode][]', '2');
body.append('exercises[][config][modes][][config][holdOpen][]', '2000');
body.append('exercises[][config][modes][][config][pulseTimings][]', '240');
body.append('exercises[][config][modes][][config][softGrip][]', '1');
body.append('exercises[][config][modes][][config][speedControlStrategy][]', '0');
body.append('exercises[][firmware_id]', '21066896');
body.append('exercises[][app_version]', '9.52.47');
body.append('exercises[][attempts][][date_start]', '2004-05-21 07:49:56');
body.append('exercises[][attempts][][date_end]', '1985-04-30 05:54:35');
body.append('exercises[][attempts][][result]', 'success');
body.append('exercises[][emg_file]', document.querySelector('input[name="exercises[][emg_file]"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());Example response (200):
[
{
"id": 1,
"user_id": 319,
"training_task_id": 1,
"date_start": "1991-06-28 22:14:07",
"date_end": "2003-01-17 04:12:17",
"end_reason": "success",
"config": "{\"common\":{\"fingerStrength\":[1,500],\"gripPositions\":{\"_\":0,\"0\":{\"initial\":[11,5,42,4,34],\"limit\":[91,77,52,83,71]},\"1\":{\"initial\":[36,65,26,12,1],\"limit\":[52,70,41,51,68]},\"2\":{\"initial\":[55,28,30,22,36],\"limit\":[88,78,43,59,63]},\"3\":{\"initial\":[31,67,41,34,10],\"limit\":[42,67,64,51,29]},\"4\":{\"initial\":[52,19,38,49,73],\"limit\":[66,77,71,93,74]},\"5\":{\"initial\":[22,24,39,29,19],\"limit\":[95,43,57,35,74]},\"6\":{\"initial\":[6,29,36,13,9],\"limit\":[34,54,62,20,30]},\"7\":{\"initial\":[42,37,17,16,8],\"limit\":[70,61,72,85,84]},\"8\":{\"initial\":[57,4,60,17,31],\"limit\":[57,28,66,74,60]},\"9\":{\"initial\":[39,25,61,3,43],\"limit\":[42,48,73,48,72]},\"10\":{\"initial\":[66,14,25,11,24],\"limit\":[93,37,45,33,32]},\"11\":{\"initial\":[5,25,50,83,28],\"limit\":[6,38,60,86,70]},\"12\":{\"initial\":[46,15,66,50,5],\"limit\":[61,56,87,93,86]},\"13\":{\"initial\":[54,44,9,80,3],\"limit\":[64,51,84,88,79]}},\"inputSite\":[0]},\"modes\":[{\"id\":86,\"name\":\"Ut non dolorem rerum odit ut nesciunt quia.\",\"slot\":0,\"config\":{\"autoGrasp\":[0,0],\"coContractionTimings\":[300,200],\"controlMode\":[0],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[50,40,30,70,100,20,80,90,50,30],\"gripPairsConfig\":[2,6,7,12,9,3,8,10],\"gripSequentialConfig\":[13,9,6,5,255,255,4,8,3,10,1,255],\"gripSwitchingMode\":[1],\"holdOpen\":[1500,2500],\"pulseTimings\":[200,180,960,770],\"softGrip\":[1],\"speedControlStrategy\":[0]}},{\"id\":87,\"name\":\"Id in velit labore velit ea.\",\"slot\":1,\"config\":{\"autoGrasp\":[0,100],\"coContractionTimings\":[500,400],\"controlMode\":[1],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[60,100,50,100,0,10,50,70,0,90],\"gripPairsConfig\":[8,6,2,5,13,1,4,3],\"gripSequentialConfig\":[11,255,12,1,255,5,255,4,7,255,8,255],\"gripSwitchingMode\":[3],\"holdOpen\":[2000,2500],\"pulseTimings\":[710,160,610,80],\"softGrip\":[0],\"speedControlStrategy\":[1]}},{\"id\":88,\"name\":\"Ea necessitatibus ad delectus dolore.\",\"slot\":2,\"config\":{\"autoGrasp\":[1,100],\"coContractionTimings\":[300,200],\"controlMode\":[0],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[0,70,70,50,90,100,60,90,10,30],\"gripPairsConfig\":[8,12,5,6,11,1,9,13],\"gripSequentialConfig\":[7,6,255,255,1,4,2,5,255,13,12,255],\"gripSwitchingMode\":[2],\"holdOpen\":[1500,2000],\"pulseTimings\":[570,790,140,310],\"softGrip\":[0],\"speedControlStrategy\":[0]}}]}",
"firmware_id": 24,
"app_version": "9.35.14",
"emg_file": "/tmp/fakeri4fsam",
"created_at": "2026-02-27T12:42:52.000000Z",
"updated_at": "2026-02-27T12:42:52.000000Z",
"attempts": [
{
"id": 1,
"training_log_id": 1,
"date_start": "2016-07-10 11:58:53",
"date_end": "1987-03-01 19:25:47",
"result": "success",
"created_at": "2026-02-27T12:42:52.000000Z",
"updated_at": "2026-02-27T12:42:52.000000Z"
}
]
},
{
"id": 3,
"user_id": 321,
"training_task_id": 3,
"date_start": "2016-10-14 08:31:26",
"date_end": "2025-10-22 18:51:07",
"end_reason": "success",
"config": "{\"common\":{\"fingerStrength\":[1,400],\"gripPositions\":{\"_\":0,\"0\":{\"initial\":[50,53,56,66,20],\"limit\":[85,56,60,81,52]},\"1\":{\"initial\":[14,29,10,33,48],\"limit\":[50,40,14,63,50]},\"2\":{\"initial\":[5,15,16,14,42],\"limit\":[28,67,16,69,73]},\"3\":{\"initial\":[10,29,4,71,3],\"limit\":[60,66,91,90,95]},\"4\":{\"initial\":[40,42,39,34,51],\"limit\":[78,76,83,60,60]},\"5\":{\"initial\":[44,79,31,45,37],\"limit\":[75,81,59,80,95]},\"6\":{\"initial\":[28,28,15,16,42],\"limit\":[52,79,62,84,93]},\"7\":{\"initial\":[29,2,60,51,43],\"limit\":[48,63,93,72,46]},\"8\":{\"initial\":[15,1,31,8,37],\"limit\":[81,53,77,15,45]},\"9\":{\"initial\":[7,12,84,23,15],\"limit\":[34,51,89,36,63]},\"10\":{\"initial\":[34,69,14,4,60],\"limit\":[41,91,94,88,86]},\"11\":{\"initial\":[61,47,2,62,5],\"limit\":[79,84,58,72,5]},\"12\":{\"initial\":[3,7,20,8,34],\"limit\":[7,16,92,84,64]},\"13\":{\"initial\":[22,25,47,4,69],\"limit\":[72,94,64,69,87]}},\"inputSite\":[0]},\"modes\":[{\"id\":92,\"name\":\"Aut voluptatem sed odio voluptas sed numquam.\",\"slot\":0,\"config\":{\"autoGrasp\":[1,0],\"coContractionTimings\":[300,300],\"controlMode\":[1],\"emgGains\":[100,100],\"emgSpike\":[1,300],\"emgThresholds\":[0,70,40,100,30,80,40,30,20,30],\"gripPairsConfig\":[2,7,5,11,12,1,10,8],\"gripSequentialConfig\":[255,255,12,13,5,4,3,255,8,11,255,9],\"gripSwitchingMode\":[1],\"holdOpen\":[2000,2500],\"pulseTimings\":[400,90,130,290],\"softGrip\":[1],\"speedControlStrategy\":[0]}},{\"id\":93,\"name\":\"Eos quis sunt qui et occaecati tenetur.\",\"slot\":1,\"config\":{\"autoGrasp\":[1,0],\"coContractionTimings\":[300,100],\"controlMode\":[1],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[70,20,100,40,100,10,10,40,80,30],\"gripPairsConfig\":[13,2,12,7,3,10,6,11],\"gripSequentialConfig\":[7,255,8,12,4,9,6,2,255,1,255,11],\"gripSwitchingMode\":[2],\"holdOpen\":[1500,1500],\"pulseTimings\":[100,360,240,440],\"softGrip\":[1],\"speedControlStrategy\":[1]}},{\"id\":94,\"name\":\"Veritatis deserunt nulla dolorem aspernatur dolor quidem.\",\"slot\":2,\"config\":{\"autoGrasp\":[0,0],\"coContractionTimings\":[400,100],\"controlMode\":[0],\"emgGains\":[100,100],\"emgSpike\":[0,300],\"emgThresholds\":[70,10,40,80,10,50,70,10,0,20],\"gripPairsConfig\":[12,7,8,9,4,2,13,1],\"gripSequentialConfig\":[10,5,3,1,255,255,8,2,255,11,255,255],\"gripSwitchingMode\":[3],\"holdOpen\":[1500,2000],\"pulseTimings\":[910,730,670,690],\"softGrip\":[0],\"speedControlStrategy\":[1]}}]}",
"firmware_id": 26,
"app_version": "4.28.23",
"emg_file": "/tmp/fakerYbHfPX",
"created_at": "2026-02-27T12:42:52.000000Z",
"updated_at": "2026-02-27T12:42:52.000000Z",
"attempts": [
{
"id": 2,
"training_log_id": 3,
"date_start": "2025-10-08 11:31:27",
"date_end": "1993-11-11 05:20:20",
"result": "success",
"created_at": "2026-02-27T12:42:52.000000Z",
"updated_at": "2026-02-27T12:42:52.000000Z"
}
]
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage user trainings",
"code": "TRAININGS:SAVE_ATTEMPTS:INSUFFICIENT_PERMISSION"
}
Example response (403, User has no training started):
{
"message": "User has no training started",
"code": "TRAININGS:SAVE_ATTEMPTS:NO_USER_TRAINING"
}
Example response (404, Training not found):
{
"message": "Training not found",
"code": "TRAININGS:SAVE_ATTEMPTS:TRAINING_NOT_FOUND"
}
Example response (404, Training day not found):
{
"message": "Training day not found",
"code": "TRAININGS:SAVE_ATTEMPTS:TRAINING_DAY_NOT_FOUND"
}
Example response (404, Training task not found):
{
"message": "Training task not found",
"code": "TRAININGS:SAVE_ATTEMPTS:TRAINING_TASK_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get reward status
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/trainings/1/reward" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/trainings/1/reward"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, Reward status):
{
"status": true
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage user trainings",
"code": "TRAININGS:REWARD_STATUS:INSUFFICIENT_PERMISSION"
}
Example response (404, Training not found):
{
"message": "Training not found",
"code": "TRAININGS:REWARD_STATUS:TRAINING_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Save reward details
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/trainings/1/reward" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"type\": \"physical\",
\"country\": \"PT\",
\"delivery\": \"pl_inpost_parcel_locker\",
\"email\": \"dewayne95@yahoo.com\",
\"phone\": \"541.853.4937\",
\"full_name\": \"Eleanore Kuhlman\",
\"address1\": \"99818 Emanuel Crest\",
\"address2\": \"Apt. 732\",
\"city\": \"Altenwerthtown\",
\"postal_code\": \"16962\",
\"state\": \"EVENIET\",
\"parcel_locker_code\": \"41U5UAX4\",
\"pin_code\": \"487598\"
}"
const url = new URL(
"http://localhost:8000/api/trainings/1/reward"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"type": "physical",
"country": "PT",
"delivery": "pl_inpost_parcel_locker",
"email": "dewayne95@yahoo.com",
"phone": "541.853.4937",
"full_name": "Eleanore Kuhlman",
"address1": "99818 Emanuel Crest",
"address2": "Apt. 732",
"city": "Altenwerthtown",
"postal_code": "16962",
"state": "EVENIET",
"parcel_locker_code": "41U5UAX4",
"pin_code": "487598"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"id": 1,
"user_id": 323,
"training_id": 21,
"type": "digital",
"country": "BG",
"delivery": "ua_nova_poshta_parcel_locker",
"email": "ephraim.hoeger@yahoo.com",
"phone": "+1-786-205-9351",
"full_name": "Lukas Lynch",
"address1": "481 Kling Village Suite 598",
"address2": "4203 Adams Fords Apt. 581\nPort Rylee, MN 48443-1919",
"city": "Larsonberg",
"postal_code": "74150",
"state": "NISI",
"parcel_locker_code": "LHLCPZN1",
"pin_code": "333250",
"created_at": "2026-02-27T12:42:52.000000Z",
"updated_at": "2026-02-27T12:42:52.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to manage user trainings",
"code": "TRAININGS:REWARD_SAVE:INSUFFICIENT_PERMISSION"
}
Example response (403, Reward details already exists):
{
"message": "Reward details already exists",
"code": "TRAININGS:REWARD_SAVE:ALREADY_EXISTS"
}
Example response (404, Training not found):
{
"message": "Training not found",
"code": "TRAININGS:REWARD_SAVE:TRAINING_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get user progress (clinician view)
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/trainings/progress/aut/user/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/trainings/progress/aut/user/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
[
{
"number": 1,
"key": "openClose",
"status": "completed",
"status_updated_at": "2026-02-04 11:00:00"
},
{
"number": 2,
"key": "holdOpen",
"status": "in_progress",
"status_updated_at": "2026-02-05 09:00:00"
},
{
"number": 3,
"key": "changeSignal",
"status": "not_started",
"status_updated_at": null
},
{
"number": 4,
"key": "thumbPositioning",
"status": "not_started",
"status_updated_at": null
},
{
"number": 5,
"key": "sequentialAndPairingMode",
"status": "not_started",
"status_updated_at": null
},
{
"number": 6,
"key": "fingerSpeedTraining",
"status": "not_started",
"status_updated_at": null
},
{
"number": 7,
"key": "freezeMode",
"status": "not_started",
"status_updated_at": null
},
{
"number": 8,
"key": "coreSkillsTest",
"status": "not_started",
"status_updated_at": null
},
{
"number": 9,
"key": "powerSoftGrip",
"status": "not_started",
"status_updated_at": null
},
{
"number": 10,
"key": "precisionGrip",
"status": "not_started",
"status_updated_at": null
},
{
"number": 11,
"key": "tripodGrip",
"status": "not_started",
"status_updated_at": null
},
{
"number": 12,
"key": "keyGrip",
"status": "not_started",
"status_updated_at": null
},
{
"number": 13,
"key": "gripSelection",
"status": "not_started",
"status_updated_at": null
},
{
"number": 14,
"key": "finalGripAndControlTest",
"status": "not_started",
"status_updated_at": null
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to access patient training",
"code": "TRAININGS:PROGRESS_CLINICIAN:INSUFFICIENT_PERMISSION"
}
Example response (404, Training not found):
{
"message": "Training not found",
"code": "TRAININGS:PROGRESS_CLINICIAN:TRAINING_NOT_FOUND"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "TRAININGS:PROGRESS_CLINICIAN:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Users
API endpoints for user management
Get users list
requires authentication
Possible extend options:
- clinicians - users assigned to this user as clinicians (for Amputee role)
- patients - users assigned to this user as patients (for ClinicAdmin/Clinician/ClinicianSupport role)
- devices - products assigned to user (for Amputee role)
- devicesAsClinician - products assigned to user as clinician (for ClinicAdmin/Clinician/ClinicianSupport role)
- roles - user roles
- permissions - user permissions (for ClinicianSupport role)
Example request:
curl --request GET \
--get "http://localhost:8000/api/users?search=Tom&active=-1&clinician[]=4&roles=Clinician%2CAmputee&has_devices=1&user_toggles=goals%2Ctrainings" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/users"
);
const params = {
"search": "Tom",
"active": "-1",
"clinician[0]": "4",
"roles": "Clinician,Amputee",
"has_devices": "1",
"user_toggles": "goals,trainings",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 7,
"mrn": "0OOK7U2K1772196142",
"name": "Dr. Frederique Ferry Sr.",
"email": "1772196142stark.torey@example.net",
"language": "en",
"phone": "+1 (917) 872-7499",
"phone_country": "GB",
"phone_verified_at": null,
"address1": "176 Keeling Point Apt. 863",
"address2": "Ankundington, WV 09203-8192",
"postal_code": "55675",
"city": "Zieme-Zboncak",
"country": "SI",
"clinic_name": "Lake Claudine",
"clinic_location": "7059 Roob Meadows\nNew General, AR 65887",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:22.000000Z",
"updated_at": "2026-02-27T12:42:22.000000Z",
"invitation_status": null,
"acadle_invitation_status": "accepted",
"clinicians": [
{
"id": 8,
"mrn": "PWOGIDAB1772196142",
"name": "Mr. Daron Dickens III",
"email": "1772196142bernhard.kali@example.net",
"language": "en",
"phone": "1-959-366-3516",
"phone_country": "BJ",
"phone_verified_at": null,
"address1": "911 Elta Ports",
"address2": "Bergstromside, FL 67329-9893",
"postal_code": "69807",
"city": "Sporer Inc",
"country": "SE",
"clinic_name": "Merlinstad",
"clinic_location": "74769 Witting Spur\nGoyetteborough, TN 24328-1558",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:22.000000Z",
"updated_at": "2026-02-27T12:42:22.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"pivot": {
"user_id": 7,
"assigned_user_id": 8
},
"roles": []
}
],
"devices": [
{
"id": 1,
"serial": "68f6308d-5815-3ff7-82a6-2e09ebc42646",
"bluetooth_id": "5d38a693-3f9a-36a2-84e8-ae9f348fe7dd",
"company_id": null,
"model_id": null,
"amputee_id": 7,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:22.000000Z",
"updated_at": "2026-02-27T12:42:22.000000Z"
}
],
"roles": [
{
"id": 6,
"name": "AcadleUser"
}
]
},
{
"id": 9,
"mrn": "BKKSBD5E1772196142",
"name": "Dorothy Sporer",
"email": "1772196142efadel@example.com",
"language": "en",
"phone": "(430) 598-9353",
"phone_country": "PT",
"phone_verified_at": null,
"address1": "61098 Mohr Turnpike Apt. 173",
"address2": "New Allisonland, ID 87059",
"postal_code": "20331-6546",
"city": "DuBuque-Bogisich",
"country": "ES",
"clinic_name": "Walkerfurt",
"clinic_location": "6759 Ruecker Key Suite 508\nBroderickburgh, OR 63587",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:22.000000Z",
"updated_at": "2026-02-27T12:42:22.000000Z",
"invitation_status": null,
"acadle_invitation_status": "accepted",
"clinicians": [
{
"id": 10,
"mrn": "72DYHAJ81772196142",
"name": "Mr. Werner Sawayn V",
"email": "1772196142wgaylord@example.net",
"language": "en",
"phone": "947-343-8003",
"phone_country": "JE",
"phone_verified_at": null,
"address1": "8558 Ada Falls Suite 048",
"address2": "North Rigoberto, CO 35738-9215",
"postal_code": "18937-8907",
"city": "Kemmer PLC",
"country": "DK",
"clinic_name": "Durganfort",
"clinic_location": "8305 Marlee Meadows\nEast Chester, NM 72444-9131",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:22.000000Z",
"updated_at": "2026-02-27T12:42:22.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"pivot": {
"user_id": 9,
"assigned_user_id": 10
},
"roles": []
}
],
"devices": [
{
"id": 2,
"serial": "abc278f6-1661-3fba-8d23-70e280c9495f",
"bluetooth_id": "fd771dc8-6277-3f66-9f76-4ee6441821e4",
"company_id": null,
"model_id": null,
"amputee_id": 9,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:22.000000Z",
"updated_at": "2026-02-27T12:42:22.000000Z"
}
],
"roles": [
{
"id": 6,
"name": "AcadleUser"
}
]
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view user list",
"code": "USERS:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get current user data
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/me" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/me"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 11,
"mrn": "WV2YHKAA1772196143",
"name": "Megane Brown",
"email": "1772196143wallace15@example.org",
"language": "en",
"phone": "(678) 579-4060",
"phone_country": "PK",
"phone_verified_at": null,
"address1": "628 Madelynn Views",
"address2": "Toybury, IA 01783",
"postal_code": "45796",
"city": "Koelpin, Herman and Gibson",
"country": "DK",
"clinic_name": "New Tatum",
"clinic_location": "775 Turcotte Meadows\nAmaliamouth, TX 08761",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:23.000000Z",
"updated_at": "2026-02-27T12:42:23.000000Z",
"invitation_status": null,
"acadle_invitation_status": "accepted",
"roles": [
{
"id": 6,
"name": "AcadleUser"
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get other user data
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/user/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/user/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"id": 12,
"mrn": "TAJ83P7T1772196143",
"name": "Hortense Quigley",
"email": "1772196143shaylee.oreilly@example.org",
"language": "en",
"phone": "1-351-850-1318",
"phone_country": "TM",
"phone_verified_at": null,
"address1": "59435 Padberg Village",
"address2": "Kuhlmanberg, CA 05641-4386",
"postal_code": "14034-8330",
"city": "Langosh, Frami and Larson",
"country": "SI",
"clinic_name": "Freddyfurt",
"clinic_location": "522 Janice Village\nWest Colleenmouth, VT 14339-6515",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:23.000000Z",
"updated_at": "2026-02-27T12:42:23.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": [
{
"id": 5,
"name": "Amputee"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view user data",
"code": "USERS:GET:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "USERS:GET:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create new user account
requires authentication
Predefined permissions:
user.view- access to view users' data (GET /user/{id} endpoint)user.update- access to update users' data (PUT /user/{id} and POST /user/{id}/phone endpoints)user.passwordChange- access to change users' passwords (POST /user/{id}/password endpoint)user.devices- access to list of users' devices (GET /user/{id}/devices endpoint)user.tickets.view- access to listing and viewing ticketsuser.tickets.update- access to updating tickets (marking messages as read)user.tickets.send- access to sending messages in ticketsuser.tickets.close- access to closing ticketsuser.goals- access to view or manage users' goals
Example request:
curl --request POST \
"http://localhost:8000/api/user" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "mrn=MRN12345678"\
--form "name=Tom Smith"\
--form "email=test@example.com"\
--form "language=en"\
--form "address1=199 Jonas Lights"\
--form "address2=New Stefanie, MA 17981-5423"\
--form "postal_code=27370-9849"\
--form "city=Mitchellhaven"\
--form "country=HU"\
--form "clinic_name=Aether"\
--form "clinic_location=199 Jonas Lights"\
--form "mfa_enabled=1"\
--form "mfa_method=email"\
--form "clinicians[]=2"\
--form "notifications_timezone=Europe/Warsaw"\
--form "notifications_at=8:00"\
--form "role=Amputee"\
--form "image=@/tmp/phpVN4eCo" const url = new URL(
"http://localhost:8000/api/user"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('mrn', 'MRN12345678');
body.append('name', 'Tom Smith');
body.append('email', 'test@example.com');
body.append('language', 'en');
body.append('address1', '199 Jonas Lights');
body.append('address2', 'New Stefanie, MA 17981-5423');
body.append('postal_code', '27370-9849');
body.append('city', 'Mitchellhaven');
body.append('country', 'HU');
body.append('clinic_name', 'Aether');
body.append('clinic_location', '199 Jonas Lights');
body.append('mfa_enabled', '1');
body.append('mfa_method', 'email');
body.append('clinicians[]', '2');
body.append('notifications_timezone', 'Europe/Warsaw');
body.append('notifications_at', '8:00');
body.append('role', 'Amputee');
body.append('image', document.querySelector('input[name="image"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());Example response (201):
{
"id": 13,
"mrn": "HE3CX2UD1772196143",
"name": "Nicolette Wiegand",
"email": "1772196143xshanahan@example.com",
"language": "en",
"phone": "+14084619312",
"phone_country": "KR",
"phone_verified_at": null,
"address1": "3092 Carmelo Square Apt. 770",
"address2": "West Hadley, MN 48689",
"postal_code": "60056-6221",
"city": "Parisian PLC",
"country": "GR",
"clinic_name": "North Janiya",
"clinic_location": "8559 Bosco Spring Suite 340\nOdellhaven, WA 87766-9569",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:23.000000Z",
"updated_at": "2026-02-27T12:42:23.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": [
{
"id": 1,
"name": "SuperAdmin"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create user with given role",
"code": "USERS:CREATE:INSUFFICIENT_PERMISSION"
}
Example response (403, E-mail in use (in another region)):
{
"message": "E-mail address already in use (in another region)",
"code": "USERS:CREATE:EMAIL_IN_USE"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update user account
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/user/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "mrn=MRN12345678"\
--form "name=Tom Smith"\
--form "email=test@example.com"\
--form "language=en"\
--form "address1=68369 Issac Meadow Apt. 912"\
--form "address2=West Heidi, CT 74676-5004"\
--form "postal_code=67062-5331"\
--form "city=Collinschester"\
--form "country=GR"\
--form "clinic_name=Aether"\
--form "clinic_location=68369 Issac Meadow Apt. 912"\
--form "image_delete=1"\
--form "mfa_enabled=1"\
--form "mfa_method=email"\
--form "active=1"\
--form "clinicians[]=2"\
--form "notifications_timezone=Europe/Warsaw"\
--form "notifications_at=8:00"\
--form "role=Amputee"\
--form "image=@/tmp/phpUTCPlR" const url = new URL(
"http://localhost:8000/api/user/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('mrn', 'MRN12345678');
body.append('name', 'Tom Smith');
body.append('email', 'test@example.com');
body.append('language', 'en');
body.append('address1', '68369 Issac Meadow Apt. 912');
body.append('address2', 'West Heidi, CT 74676-5004');
body.append('postal_code', '67062-5331');
body.append('city', 'Collinschester');
body.append('country', 'GR');
body.append('clinic_name', 'Aether');
body.append('clinic_location', '68369 Issac Meadow Apt. 912');
body.append('image_delete', '1');
body.append('mfa_enabled', '1');
body.append('mfa_method', 'email');
body.append('active', '1');
body.append('clinicians[]', '2');
body.append('notifications_timezone', 'Europe/Warsaw');
body.append('notifications_at', '8:00');
body.append('role', 'Amputee');
body.append('image', document.querySelector('input[name="image"]').files[0]);
fetch(url, {
method: "PUT",
headers,
body,
}).then(response => response.json());Example response (202):
{
"id": 14,
"mrn": "CCE8RA561772196143",
"name": "Celestino Adams",
"email": "1772196143kpollich@example.com",
"language": "en",
"phone": "608.201.2198",
"phone_country": "TF",
"phone_verified_at": null,
"address1": "409 Bergnaum Run Suite 537",
"address2": "Addieland, RI 07405-1968",
"postal_code": "41970-1334",
"city": "Gerhold, Runte and Schamberger",
"country": "BE",
"clinic_name": "Balistreriland",
"clinic_location": "20722 Powlowski Orchard\nKarliehaven, KS 83141",
"image": null,
"mfa_enabled": 0,
"mfa_method": null,
"mfa_verified_to": null,
"location_id": null,
"created_by": null,
"active": 1,
"notifications_timezone": null,
"notifications_at": null,
"created_at": "2026-02-27T12:42:23.000000Z",
"updated_at": "2026-02-27T12:42:23.000000Z",
"invitation_status": null,
"acadle_invitation_status": null,
"roles": [
{
"id": 5,
"name": "Amputee"
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update user data",
"code": "USERS:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (403, Insufficient permission to assign role):
{
"message": "Insufficient permission to assign this role as ClinicAdmin",
"code": "USERS:UPDATE:INSUFFICIENT_PERMISSION_ASSIGN_ROLE"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "USERS:UPDATE:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update user phone number
requires authentication
Phone number has to be verified after update.
Call /api/mfa/phone/verify with user-filled code after performing this operation.
If value is "0" phone number will be removed without any verification.
Example request:
curl --request POST \
"http://localhost:8000/api/user/1/phone" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"phone\": \"+1 (208) 892-0242\",
\"phone_country\": \"US\"
}"
const url = new URL(
"http://localhost:8000/api/user/1/phone"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"phone": "+1 (208) 892-0242",
"phone_country": "US"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Phone number removed):
{
"message": "Phone number removed",
"code": "USERS:SET_PHONE:REMOVED"
}
Example response (200, Phone number updated):
{
"message": "Verification code sent. Call /api/mfa/phone/verify to verify phone number.",
"code": "USERS:SET_PHONE:UPDATED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update user data",
"code": "USERS:SET_PHONE:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "USERS:SET_PHONE:USER_NOT_FOUND"
}
Example response (500, Code send failed):
{
"message": "Verification code sending failed",
"code": "USERS:SET_PHONE:SEND_FAILED"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete user account
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/user/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/user/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "User deleted",
"code": "USERS:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to delete user",
"code": "USERS:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (403, User has existing patients or chat rooms):
{
"message": "Cannot delete: user has existing patients or chat rooms (patients: 1, chat rooms: 0)",
"code": "USERS:DELETE:HAS_PATIENTS"
}
Example response (403, User has existing devices):
{
"message": "Cannot delete: user has existing devices (as patient: 1, as clinician: 0)",
"code": "USERS:DELETE:HAS_DEVICES"
}
Example response (403, User has open P2P sessions):
{
"message": "Cannot delete: user has open P2P sessions (as patient: 0, as clinician: 1)",
"code": "USERS:DELETE:HAS_P2P_SESSIONS"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "USERS:DELETE:USER_NOT_FOUND"
}
Example response (500, Server error):
{
"message": "Server error: user not deleted",
"code": "USERS:DELETE:SERVER_ERROR"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete own user account
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/user" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/user"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "User deleted",
"code": "USERS:SELF_DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to delete user",
"code": "USERS:SELF_DELETE:INSUFFICIENT_PERMISSION"
}
Example response (500, Server error):
{
"message": "Server error: user not deleted",
"code": "USERS:SELF_DELETE:SERVER_ERROR"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Change other user password
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/user/1/password" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"password\": \"quis\"
}"
const url = new URL(
"http://localhost:8000/api/user/1/password"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"password": "quis"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202, OK):
{
"message": "User password changed",
"code": "USERS:PASSWORD_CHANGE:CHANGED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to change user password",
"code": "USERS:PASSWORD_CHANGE:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "USERS:PASSWORD_CHANGE:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get user devices list
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/user/1/devices" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/user/1/devices"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 3,
"serial": "778ec994-71cf-3f63-960b-fae113f495f4",
"bluetooth_id": "63cb0ca1-0b25-3ec3-a9e5-2b042ed34fe0",
"company_id": null,
"model_id": 1,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:23.000000Z",
"updated_at": "2026-02-27T12:42:23.000000Z",
"model": {
"id": 1,
"name": "Zeus hand v1",
"type": "arm",
"orientation": "left",
"active": 1,
"created_at": "2026-02-27T12:42:23.000000Z",
"updated_at": "2026-02-27T12:42:23.000000Z"
}
},
{
"id": 4,
"serial": "85a22c97-35de-386f-9e02-9520d899011d",
"bluetooth_id": "68b440d2-a799-34c1-9c52-a6afe4c5533b",
"company_id": null,
"model_id": 2,
"amputee_id": null,
"clinician_id": null,
"firmware_version_id": null,
"pcb_version_id": null,
"reverse_magnets": 0,
"is_electrode": 0,
"active": 1,
"last_activity_at": "0000-00-00 00:00:00",
"created_at": "2026-02-27T12:42:23.000000Z",
"updated_at": "2026-02-27T12:42:23.000000Z",
"model": {
"id": 2,
"name": "Zeus hand v1",
"type": "arm",
"orientation": "left",
"active": 1,
"created_at": "2026-02-27T12:42:23.000000Z",
"updated_at": "2026-02-27T12:42:23.000000Z"
}
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to view user devices",
"code": "USERS:DEVICES:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "USERS:DEVICES:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Attach patient to clinician
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/user/attach" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"name@domain.com\"
}"
const url = new URL(
"http://localhost:8000/api/user/attach"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "name@domain.com"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202, OK):
{
"message": "Patient attached",
"code": "USERS:ATTACH:ATTACHED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to attach patients",
"code": "USERS:ATTACH:INSUFFICIENT_PERMISSION"
}
Example response (403, Patient is already assigned to another clinician):
{
"message": "Patient is already assigned to another clinician",
"code": "USERS:ATTACH:ALREADY_ASSIGNED"
}
Example response (403, User reached the temporary limit of attached devices):
{
"message": "Reached the limit of assigned devices",
"code": "USERS:ATTACH:LIMIT_REACHED"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "USERS:ATTACH:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Detach patient from clinician
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/user/1/detach" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/user/1/detach"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Patient detached",
"code": "USERS:DETACH:DETACHED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to detach patient",
"code": "USERS:DETACH:INSUFFICIENT_PERMISSION"
}
Example response (403, Cannot detach last clinician):
{
"message": "Cannot detach patient's last clinician",
"code": "USERS:DETACH:CANNOT_DETACH_LAST_CLINICIAN"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "USERS:DETACH:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Admin access to MFA codes
requires authentication
Requires admin.mfa_access permission.
Example request:
curl --request GET \
--get "http://localhost:8000/api/user/1/mfa-codes" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/user/1/mfa-codes"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, OK):
[
{
"id": 1,
"user_id": 1,
"code": "123456",
"channel": "email",
"expires": "2025-05-09 12:00:00"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to access MFA codes",
"code": "USERS:ADMIN_MFA_ACCESS:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "USERS:ADMIN_MFA_ACCESS:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get user mobile consents
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/consents" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/consents"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 1,
"user_id": 1,
"name": "eaque",
"value": "laborum",
"created_at": "1978-10-19T18:10:53.000000Z",
"updated_at": "2020-04-09T20:08:39.000000Z"
},
{
"id": 2,
"user_id": 1,
"name": "tempora",
"value": "veniam",
"created_at": "1993-08-25T21:31:20.000000Z",
"updated_at": "1989-06-22T15:15:21.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to use mobile consents",
"code": "USERS:GET_MOBILE_CONSENTS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Set user mobile consent
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/consents" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Push notifications\",
\"value\": 1
}"
const url = new URL(
"http://localhost:8000/api/consents"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Push notifications",
"value": 1
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
[
{
"id": 3,
"user_id": 1,
"name": "rem",
"value": "ab",
"created_at": "2010-10-02T20:02:17.000000Z",
"updated_at": "1974-05-04T22:59:42.000000Z"
},
{
"id": 4,
"user_id": 1,
"name": "perspiciatis",
"value": "vero",
"created_at": "1994-05-04T05:55:39.000000Z",
"updated_at": "2022-01-02T23:02:54.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to use mobile consents",
"code": "USERS:SET_MOBILE_CONSENTS:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Clear user notifications
requires authentication
Clearing notifications allow to receive another notification on same day. This endpoint deletes notifications of type:
- daily activity reminders
- goals daily summary
This endpoint is intended for testing use only.
Example request:
curl --request DELETE \
"http://localhost:8000/api/notifications/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/notifications/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"messages": "1 notifications deleted",
"code": "USERS:CLEAR_NOTIFICATIONS:CLEARED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update user data",
"code": "USERS:CLEAR_NOTIFICATIONS:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "USERS:CLEAR_NOTIFICATIONS:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Versions
API endpoints for versions management
Get software versions
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/versions/software" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/versions/software"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 1,
"name": "6.62.0",
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
},
{
"id": 2,
"name": "1.52.59",
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list versions",
"code": "SOFTWARE_VERSION:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create software version
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/versions/software" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"1.0\"
}"
const url = new URL(
"http://localhost:8000/api/versions/software"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "1.0"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 3,
"name": "4.97.91",
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create versions",
"code": "SOFTWARE_VERSION:CREATE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete software version
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/versions/software/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/versions/software/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Version deleted",
"code": "SOFTWARE_VERSION:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to delete versions",
"code": "SOFTWARE_VERSION:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (403, Version in use (compatibility)):
{
"message": "Cannot delete: version is used in compatibility entries (1)",
"code": "SOFTWARE_VERSION:DELETE:VERSION_IN_USE_COMPATIBILITY"
}
Example response (404, Version not found):
{
"message": "Version not found",
"code": "SOFTWARE_VERSION:DELETE:VERSION_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get firmware versions
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/versions/firmware" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/versions/firmware"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 2,
"name": "5.3.5",
"file_firmware": "/tmp/fakerWxIh6a",
"file_firmware_v2": "/tmp/fakerOsuHrn",
"file_firmware_v3": "/tmp/fakerodlX1a",
"file_firmware_v4": "/tmp/fakera3dNvL",
"file_firmware_v5": "/tmp/faker8hy1TK",
"file_firmware_new_pcb": "/tmp/fakerKDnFM7",
"file_bootloader": "/tmp/fakerkQUT0V",
"file_bootloader_v2": "/tmp/faker38um9q",
"file_bootloader_v3": "/tmp/fakery9rPE3",
"file_bootloader_v4": "/tmp/fakerYtHl18",
"changelog": "Quibusdam optio nostrum voluptas optio nihil. Ipsum explicabo assumenda nam incidunt doloremque. Adipisci cum amet veniam consectetur.",
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
},
{
"id": 3,
"name": "4.76.82",
"file_firmware": "/tmp/fakerqbtgIT",
"file_firmware_v2": "/tmp/fakerMZuDbw",
"file_firmware_v3": "/tmp/faker2ElGi0",
"file_firmware_v4": "/tmp/faker4EPdH1",
"file_firmware_v5": "/tmp/fakerh689bC",
"file_firmware_new_pcb": "/tmp/faker5GC6QV",
"file_bootloader": "/tmp/faker0G468k",
"file_bootloader_v2": "/tmp/fakerxEMmg0",
"file_bootloader_v3": "/tmp/fakerJptoPH",
"file_bootloader_v4": "/tmp/fakeru0ZwHO",
"changelog": "Sit totam asperiores est eos eaque sint. Est sit non est ab nostrum ex. Dolorem in nesciunt aut quod. Mollitia sed qui voluptatibus quo et ad in.",
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list versions",
"code": "FIRMWARE_VERSION:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create firmware version
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/versions/firmware" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "name=1.0"\
--form "models[]=1"\
--form "changelog[][language]=en"\
--form "changelog[][changelog]=Fixed bug with the connection"\
--form "file_firmware=@/tmp/phpH4taMu" \
--form "file_firmware_v2=@/tmp/phpGfyrIf" \
--form "file_firmware_v3=@/tmp/phpDdeN7P" \
--form "file_firmware_v4=@/tmp/phpR3ucnD" \
--form "file_firmware_v5=@/tmp/phpNOKrjH" \
--form "file_firmware_new_pcb=@/tmp/phpbXzk32" \
--form "file_bootloader=@/tmp/phpNf9xwt" \
--form "file_bootloader_v2=@/tmp/phplwutlJ" \
--form "file_bootloader_v3=@/tmp/phpK8DCVT" \
--form "file_bootloader_v4=@/tmp/php7v0JRY" const url = new URL(
"http://localhost:8000/api/versions/firmware"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('name', '1.0');
body.append('models[]', '1');
body.append('changelog[][language]', 'en');
body.append('changelog[][changelog]', 'Fixed bug with the connection');
body.append('file_firmware', document.querySelector('input[name="file_firmware"]').files[0]);
body.append('file_firmware_v2', document.querySelector('input[name="file_firmware_v2"]').files[0]);
body.append('file_firmware_v3', document.querySelector('input[name="file_firmware_v3"]').files[0]);
body.append('file_firmware_v4', document.querySelector('input[name="file_firmware_v4"]').files[0]);
body.append('file_firmware_v5', document.querySelector('input[name="file_firmware_v5"]').files[0]);
body.append('file_firmware_new_pcb', document.querySelector('input[name="file_firmware_new_pcb"]').files[0]);
body.append('file_bootloader', document.querySelector('input[name="file_bootloader"]').files[0]);
body.append('file_bootloader_v2', document.querySelector('input[name="file_bootloader_v2"]').files[0]);
body.append('file_bootloader_v3', document.querySelector('input[name="file_bootloader_v3"]').files[0]);
body.append('file_bootloader_v4', document.querySelector('input[name="file_bootloader_v4"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());Example response (201):
{
"id": 4,
"name": "5.64.48",
"file_firmware": "/tmp/fakerDSWkKe",
"file_firmware_v2": "/tmp/fakerZ0jdKL",
"file_firmware_v3": "/tmp/fakerc4DKzD",
"file_firmware_v4": "/tmp/fakerqEqh2m",
"file_firmware_v5": "/tmp/fakerhLhw4b",
"file_firmware_new_pcb": "/tmp/fakerAUVBKR",
"file_bootloader": "/tmp/faker0lkEBt",
"file_bootloader_v2": "/tmp/fakersX5DHp",
"file_bootloader_v3": "/tmp/faker54FGkr",
"file_bootloader_v4": "/tmp/fakerEYJl5G",
"changelog": "Ut sunt ea odio dignissimos incidunt dicta suscipit dolorem. Quisquam distinctio ipsa consequatur id saepe vel. Officiis sint aliquid in.",
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create versions",
"code": "FIRMWARE_VERSION:CREATE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update firmware version
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/versions/firmware/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "name=1.0"\
--form "models[]=1"\
--form "file_firmware_delete=1"\
--form "file_firmware_v2_delete=1"\
--form "file_firmware_v3_delete=1"\
--form "file_firmware_v4_delete=1"\
--form "file_firmware_v5_delete=1"\
--form "file_firmware_new_pcb_delete=1"\
--form "file_bootloader_delete=1"\
--form "file_bootloader_v2_delete=1"\
--form "file_bootloader_v3_delete=1"\
--form "file_bootloader_v4_delete=1"\
--form "changelog[][language]=en"\
--form "changelog[][changelog]=Fixed bug with the connection"\
--form "file_firmware=@/tmp/phpERidxG" \
--form "file_firmware_v2=@/tmp/phpu6qtEB" \
--form "file_firmware_v3=@/tmp/phpdMQh2m" \
--form "file_firmware_v4=@/tmp/php9QYT7U" \
--form "file_firmware_v5=@/tmp/phpPqZ6La" \
--form "file_firmware_new_pcb=@/tmp/php0B2r8W" \
--form "file_bootloader=@/tmp/phpryNvLb" \
--form "file_bootloader_v2=@/tmp/phpXMZmos" \
--form "file_bootloader_v3=@/tmp/php6IQzxX" \
--form "file_bootloader_v4=@/tmp/php56Al5J" const url = new URL(
"http://localhost:8000/api/versions/firmware/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('name', '1.0');
body.append('models[]', '1');
body.append('file_firmware_delete', '1');
body.append('file_firmware_v2_delete', '1');
body.append('file_firmware_v3_delete', '1');
body.append('file_firmware_v4_delete', '1');
body.append('file_firmware_v5_delete', '1');
body.append('file_firmware_new_pcb_delete', '1');
body.append('file_bootloader_delete', '1');
body.append('file_bootloader_v2_delete', '1');
body.append('file_bootloader_v3_delete', '1');
body.append('file_bootloader_v4_delete', '1');
body.append('changelog[][language]', 'en');
body.append('changelog[][changelog]', 'Fixed bug with the connection');
body.append('file_firmware', document.querySelector('input[name="file_firmware"]').files[0]);
body.append('file_firmware_v2', document.querySelector('input[name="file_firmware_v2"]').files[0]);
body.append('file_firmware_v3', document.querySelector('input[name="file_firmware_v3"]').files[0]);
body.append('file_firmware_v4', document.querySelector('input[name="file_firmware_v4"]').files[0]);
body.append('file_firmware_v5', document.querySelector('input[name="file_firmware_v5"]').files[0]);
body.append('file_firmware_new_pcb', document.querySelector('input[name="file_firmware_new_pcb"]').files[0]);
body.append('file_bootloader', document.querySelector('input[name="file_bootloader"]').files[0]);
body.append('file_bootloader_v2', document.querySelector('input[name="file_bootloader_v2"]').files[0]);
body.append('file_bootloader_v3', document.querySelector('input[name="file_bootloader_v3"]').files[0]);
body.append('file_bootloader_v4', document.querySelector('input[name="file_bootloader_v4"]').files[0]);
fetch(url, {
method: "PUT",
headers,
body,
}).then(response => response.json());Example response (201):
{
"id": 5,
"name": "2.95.42",
"file_firmware": "/tmp/fakero2JjBW",
"file_firmware_v2": "/tmp/fakerqzZAko",
"file_firmware_v3": "/tmp/fakerMqJwBs",
"file_firmware_v4": "/tmp/fakernqpNfj",
"file_firmware_v5": "/tmp/faker0NFuD3",
"file_firmware_new_pcb": "/tmp/fakerCSD3dd",
"file_bootloader": "/tmp/fakerdRiOxs",
"file_bootloader_v2": "/tmp/fakerjswoyD",
"file_bootloader_v3": "/tmp/faker5R9g46",
"file_bootloader_v4": "/tmp/fakerlu8DoR",
"changelog": "Repellendus autem aut repellat praesentium soluta tenetur. Libero et necessitatibus ipsam adipisci. Quas voluptatem esse est sed sequi earum et.",
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update versions",
"code": "FIRMWARE_VERSION:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Version not found):
{
"message": "Version not found",
"code": "FIRMWARE_VERSION:UPDATE:VERSION_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete firmware version
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/versions/firmware/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/versions/firmware/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Version deleted",
"code": "FIRMWARE_VERSION:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to delete versions",
"code": "FIRMWARE_VERSION:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (403, Version in use (compatibility)):
{
"message": "Cannot delete: version is used in compatibility entries (1)",
"code": "FIRMWARE_VERSION:DELETE:VERSION_IN_USE_COMPATIBILITY"
}
Example response (403, Version in use (device)):
{
"message": "Cannot delete: version is assigned to devices (1)",
"code": "FIRMWARE_VERSION:DELETE:VERSION_IN_USE_DEVICE"
}
Example response (404, Version not found):
{
"message": "Version not found",
"code": "FIRMWARE_VERSION:DELETE:VERSION_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get PCB versions
requires authentication
Example request:
curl --request GET \
--get "http://localhost:8000/api/versions/pcb" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/versions/pcb"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 2,
"name": "5.69.68",
"hardware_id": "",
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
},
{
"id": 3,
"name": "8.3.33",
"hardware_id": "",
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list versions",
"code": "PCB_VERSION:LIST:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create PCB version
requires authentication
Example request:
curl --request POST \
"http://localhost:8000/api/versions/pcb" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"1.0\",
\"models\": [
1
],
\"hardware_id\": \"1\"
}"
const url = new URL(
"http://localhost:8000/api/versions/pcb"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "1.0",
"models": [
1
],
"hardware_id": "1"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 4,
"name": "3.47.42",
"hardware_id": "",
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to create versions",
"code": "PCB_VERSION:CREATE:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update PCB version
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/versions/pcb/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"1.0\",
\"models\": [
1
],
\"hardware_id\": \"1\"
}"
const url = new URL(
"http://localhost:8000/api/versions/pcb/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "1.0",
"models": [
1
],
"hardware_id": "1"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"id": 5,
"name": "1.63.0",
"hardware_id": "",
"created_at": "2026-02-27T12:42:44.000000Z",
"updated_at": "2026-02-27T12:42:44.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update versions",
"code": "PCB_VERSION:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Version not found):
{
"message": "Version not found",
"code": "PCB_VERSION:UPDATE:VERSION_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete PCB version
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/versions/pcb/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/versions/pcb/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Version deleted",
"code": "PCB_VERSION:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to delete versions",
"code": "PCB_VERSION:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (403, Version in use (compatibility)):
{
"message": "Cannot delete: version is used in compatibility entries (1)",
"code": "PCB_VERSION:DELETE:VERSION_IN_USE_COMPATIBILITY"
}
Example response (403, Version in use (device)):
{
"message": "Cannot delete: version is assigned to devices (1)",
"code": "PCB_VERSION:DELETE:VERSION_IN_USE_DEVICE"
}
Example response (404, Version not found):
{
"message": "Version not found",
"code": "PCB_VERSION:DELETE:VERSION_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List compatibilities
requires authentication
Most typical scenarios to use compatibility matrix:
- full matrix (no filters) - for admin panel displaying,
- filtered by all of the versions (software, firmware, PCB and device model) - for checking specific scenario compatibility and supported features.
Example request:
curl --request GET \
--get "http://localhost:8000/api/versions/compatibility?model=1&software=1.2&firmware=1.5&pcb=1.0&summary=" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/versions/compatibility"
);
const params = {
"model": "1",
"software": "1.2",
"firmware": "1.5",
"pcb": "1.0",
"summary": "0",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"paginator": {
"total": 2,
"count": 2,
"perpage": 20,
"current_page": 1,
"last_page": 1
},
"items": [
{
"id": 1,
"device_model_id": 10,
"software_version_id": 4,
"firmware_version_id": 14,
"pcb_version_id": 6,
"is_fully_compatible": 0,
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z",
"features": [
{
"id": 1,
"compatibility_id": 1,
"feature_id": 5,
"is_compatible": 0,
"reason": "Voluptatem non quaerat qui. Et fugiat omnis suscipit inventore et ut porro qui. Voluptatem laborum aut quaerat sit officia dolorum fuga.",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z",
"feature": {
"id": 5,
"name": "green",
"slug": "eum-impedit-quo-optio-et",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
},
{
"id": 2,
"compatibility_id": 1,
"feature_id": 7,
"is_compatible": 1,
"reason": "Voluptatem eos corporis ex minus tempore et cum. Tempora voluptatem esse rem nostrum vel sit. Est id odio cumque harum aut nobis. Nulla nobis accusantium totam dolorem.",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z",
"feature": {
"id": 7,
"name": "teal",
"slug": "quo-earum-nisi-rerum-est",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
},
{
"id": 3,
"compatibility_id": 1,
"feature_id": 9,
"is_compatible": 1,
"reason": "Et a excepturi voluptatem itaque minima. Repellendus quos sed fuga quasi temporibus. Sunt magni minima et. Sed illo sed consequatur assumenda amet veniam fugit rerum.",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z",
"feature": {
"id": 9,
"name": "gray",
"slug": "et-quas-ad-a-autem-quia",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
}
]
},
{
"id": 5,
"device_model_id": 14,
"software_version_id": 8,
"firmware_version_id": 18,
"pcb_version_id": 10,
"is_fully_compatible": 1,
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z",
"features": [
{
"id": 4,
"compatibility_id": 5,
"feature_id": 10,
"is_compatible": 1,
"reason": "Nostrum voluptates officiis asperiores qui voluptas aspernatur. Placeat vero sit illo sapiente. Similique sit optio quia soluta commodi sunt harum. Nemo tempore id repudiandae aut deserunt.",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z",
"feature": {
"id": 10,
"name": "yellow",
"slug": "dolorum-velit-ut-id-porro",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
},
{
"id": 5,
"compatibility_id": 5,
"feature_id": 12,
"is_compatible": 1,
"reason": "Quia repudiandae est et ad sed amet. Officiis doloribus quae sint iusto quibusdam quae asperiores. Id occaecati quae et pariatur. Mollitia molestiae quibusdam consequatur sequi.",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z",
"feature": {
"id": 12,
"name": "teal",
"slug": "ut-neque-ea-et-assumenda-ipsam-nobis",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
},
{
"id": 6,
"compatibility_id": 5,
"feature_id": 14,
"is_compatible": 0,
"reason": "Ex dolorem iste reprehenderit cumque impedit voluptatem. Nesciunt consequatur dolore ea dignissimos. Dolorem omnis quibusdam dolore excepturi repellendus. Et ut fugiat et amet dolor aut.",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z",
"feature": {
"id": 14,
"name": "navy",
"slug": "nemo-impedit-tempora-quod-recusandae-mollitia-voluptates",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
}
]
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to list versions compatibilities",
"code": "COMPATIBILITY:LIST:INSUFFICIENT_PERMISSION"
}
Example response (404, Device model not found):
{
"message": "Device model not found",
"code": "COMPATIBILITY:LIST:DEVICE_MODEL_NOT_FOUND"
}
Example response (404, Software version not found):
{
"message": "Software version not found",
"code": "COMPATIBILITY:LIST:SOFTWARE_VERSION_NOT_FOUND"
}
Example response (404, Firmware version not found):
{
"message": "Firmware version not found",
"code": "COMPATIBILITY:LIST:FIRMWARE_VERSION_NOT_FOUND"
}
Example response (404, PCB version not found):
{
"message": "PCB version not found",
"code": "COMPATIBILITY:LIST:PCB_VERSION_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Add compatibility
requires authentication
Adds or updates compatibility matrix with assigned features. You can specify many versions for each list.
Example request:
curl --request POST \
"http://localhost:8000/api/versions/compatibility" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"device_models\": [
1
],
\"software_versions\": [
1
],
\"firmware_versions\": [
1
],
\"pcb_versions\": [
1
],
\"is_fully_compatible\": true,
\"features\": [
{
\"feature_id\": 1,
\"compatible\": true,
\"reason\": \"Firmware does not support...\"
}
]
}"
const url = new URL(
"http://localhost:8000/api/versions/compatibility"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"device_models": [
1
],
"software_versions": [
1
],
"firmware_versions": [
1
],
"pcb_versions": [
1
],
"is_fully_compatible": true,
"features": [
{
"feature_id": 1,
"compatible": true,
"reason": "Firmware does not support..."
}
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202, OK):
{
"added": 1,
"updated": 0,
"not_changed": 0
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to add versions compatibility",
"code": "COMPATIBILITY:ADD:INSUFFICIENT_PERMISSION"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update compatibility
requires authentication
Example request:
curl --request PUT \
"http://localhost:8000/api/versions/compatibility/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"device_model_id\": 4,
\"software_version_id\": 13,
\"firmware_version_id\": 5,
\"pcb_version_id\": 5,
\"is_fully_compatible\": true,
\"features\": [
{
\"id\": 1,
\"feature_id\": 1,
\"compatible\": true,
\"reason\": \"Firmware does not support...\",
\"delete\": true
}
]
}"
const url = new URL(
"http://localhost:8000/api/versions/compatibility/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"device_model_id": 4,
"software_version_id": 13,
"firmware_version_id": 5,
"pcb_version_id": 5,
"is_fully_compatible": true,
"features": [
{
"id": 1,
"feature_id": 1,
"compatible": true,
"reason": "Firmware does not support...",
"delete": true
}
]
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (202):
{
"id": 9,
"device_model_id": 18,
"software_version_id": 12,
"firmware_version_id": 22,
"pcb_version_id": 14,
"is_fully_compatible": 1,
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z",
"features": [
{
"id": 7,
"compatibility_id": 9,
"feature_id": 15,
"is_compatible": 0,
"reason": "Qui doloremque impedit laboriosam maxime dolorem. Maxime qui sed sed dolorem rerum ut. Et modi consequatur qui pariatur sapiente sed illo sequi. Ab tenetur velit ipsam quia architecto.",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z",
"feature": {
"id": 15,
"name": "purple",
"slug": "recusandae-expedita-totam-perferendis-numquam",
"created_at": "2026-02-27T12:42:45.000000Z",
"updated_at": "2026-02-27T12:42:45.000000Z"
}
}
]
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to update versions compatibility",
"code": "COMPATIBILITY:UPDATE:INSUFFICIENT_PERMISSION"
}
Example response (404, Versions Compatibility not found):
{
"message": "Versions compatibility not found",
"code": "COMPATIBILITY:UPDATE:COMPATIBILITY_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete compatibility
requires authentication
Example request:
curl --request DELETE \
"http://localhost:8000/api/versions/compatibility/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/versions/compatibility/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Versions compatibility deleted",
"code": "COMPATIBILITY:DELETE:DELETED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to delete versions compatibility",
"code": "COMPATIBILITY:DELETE:INSUFFICIENT_PERMISSION"
}
Example response (404, Versions compatibility not found):
{
"message": "Versions compatibility not found",
"code": "COMPATIBILITY:DELETE:COMPATIBILITY_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Video sessions
API endpoints for managing video sessions
List video sessions
requires authentication
Returns list of open video sessions. For most cases there should be exactly one entry (open/active session) or exactly zero entries (empty array, no open sessions).
Example request:
curl --request GET \
--get "http://localhost:8000/api/sessions/video/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/sessions/video/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
[
{
"id": 1,
"moderator_id": 122,
"guest_id": 123,
"jwt_moderator": "584178e5e3517ddcebc66340917adc3a27ce4be359a29aa827563d481ff5d67a",
"jwt_guest": "f22e89c251e50eec7c9e184f5584b99fdf48fdbde7317acd6388ce05ea691a43",
"room_name": "room_94735e803b252bc16ccd9f12ff4855cf",
"expires": 1772197054,
"status": "open",
"created_at": "2026-02-27T12:42:34.000000Z",
"updated_at": "2026-02-27T12:42:34.000000Z"
},
{
"id": 2,
"moderator_id": 126,
"guest_id": 127,
"jwt_moderator": "ed68511884c42fd03769885fda404e617b59e9c20ff26e0864290df6ec2255ef",
"jwt_guest": "f056b8cae37dc3ed60ee52da9a2951f8a6c531fe3222a3ad6835dbdd905c7d2a",
"room_name": "room_94735e803b252bc16ccd9f12ff4855cf",
"expires": 1772197054,
"status": "open",
"created_at": "2026-02-27T12:42:34.000000Z",
"updated_at": "2026-02-27T12:42:34.000000Z"
}
]
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to access video session",
"code": "VIDEO_SESSIONS:LIST:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "VIDEO_SESSIONS:LIST:USER_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Initialize video session
requires authentication
Creates JWT (JSON Web Token) and room name for Jitsi session. Logged-in user is a moderator of the session. JWT lifetime is 15 minutes.
Example request:
curl --request POST \
"http://localhost:8000/api/sessions/video/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/sessions/video/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (201):
{
"id": 3,
"moderator_id": 130,
"guest_id": 131,
"jwt_moderator": "5fb156a0b8bf904b197f0245cf41fb44cb2afdbf2b4c58195ceed2865b4284ca",
"jwt_guest": "18b0a5cf1a7565679ecd1f845ca85ac1870c5b4e927fbd717784b71243dc287d",
"room_name": "room_94735e803b252bc16ccd9f12ff4855cf",
"expires": 1772197054,
"status": "open",
"created_at": "2026-02-27T12:42:34.000000Z",
"updated_at": "2026-02-27T12:42:34.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to initialize video session",
"code": "VIDEO_SESSIONS:INIT:INSUFFICIENT_PERMISSION"
}
Example response (404, User not found):
{
"message": "User not found",
"code": "VIDEO_SESSIONS:INIT:USER_NOT_FOUND"
}
Example response (500, Server error):
{
"message": "Server error",
"code": "VIDEO_SESSIONS:INIT:SERVER_ERROR"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Refresh video session
requires authentication
Refreshes video session JWT tokens to extend session lifetime.
Example request:
curl --request POST \
"http://localhost:8000/api/sessions/video/1/refresh" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/sessions/video/1/refresh"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (202):
{
"id": 4,
"moderator_id": 134,
"guest_id": 135,
"jwt_moderator": "61de7ba6838bde2a7d9a58e0c45434f7174ee4df8dce4493378d5688255cc22d",
"jwt_guest": "068e5551eb7da7ee9872e8877a674514dbaa48c0cc1407d8125fe39521ccac95",
"room_name": "room_94735e803b252bc16ccd9f12ff4855cf",
"expires": 1772197054,
"status": "open",
"created_at": "2026-02-27T12:42:35.000000Z",
"updated_at": "2026-02-27T12:42:35.000000Z"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to refresh video session",
"code": "VIDEO_SESSIONS:REFRESH:INSUFFICIENT_PERMISSION"
}
Example response (404, Session not found):
{
"message": "Video session not found",
"code": "VIDEO_SESSIONS:REFRESH:SESSION_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Close video session
requires authentication
Marks video session (database entry) as closed. Does not close session on Jitsi side.
Example request:
curl --request DELETE \
"http://localhost:8000/api/sessions/video/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/sessions/video/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (202, OK):
{
"message": "Video session closed",
"code": "VIDEO_SESSIONS:CLOSE:CLOSED"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to close video session",
"code": "VIDEO_SESSIONS:CLOSE:INSUFFICIENT_PERMISSION"
}
Example response (404, Session not found):
{
"message": "Video session not found",
"code": "VIDEO_SESSIONS:CLOSE:SESSION_NOT_FOUND"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Invite technical support
requires authentication
Sends notification to Slack channel. Link to meeting is valid for 10 minutes.
Example request:
curl --request POST \
"http://localhost:8000/api/sessions/video/invite-support/1" \
--header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"room\": \"room_1081c785cf1464e4d6ebc3976561d490\",
\"description\": \"Grip switching is not working, please join.\"
}"
const url = new URL(
"http://localhost:8000/api/sessions/video/invite-support/1"
);
const headers = {
"Authorization": "Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"room": "room_1081c785cf1464e4d6ebc3976561d490",
"description": "Grip switching is not working, please join."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, OK):
{
"response": "success",
"code": "VIDEO_SESSIONS:INVITE_TECH_SUPPORT:SUCCESS"
}
Example response (403, Insufficient permission):
{
"message": "Insufficient permission to invite tech support",
"code": "VIDEO_SESSIONS:INVITE_TECH_SUPPORT:INSUFFICIENT_PERMISSION"
}
Example response (404, Device not found):
{
"message": "Device not found",
"code": "VIDEO_SESSIONS:INVITE_TECH_SUPPORT:DEVICE_NOT_FOUND"
}
Example response (500, Request failed):
{
"response": "invalid_payload",
"code": "VIDEO_SESSIONS:INVITE_TECH_SUPPORT:FAILED"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.