[#445] How to book with the appt via the API, getting error about "Client with given id not found"

Migrated from Redmine #445 | Author: Arian Hojat
Status: Resolved | Priority: Low, I can wait | Created: 2019-11-14


I’m trying to do one of the more advanced operations now… booking an appointment.
I’m getting an error and not sure why.
Its complaining about the client/id, yet the other api calls I do with the same api info/session are fine.

Fatal error: Uncaught Exception: Request error: Client with given id not found in /var/www/html/tests/appt/JsonRpcClient.php:57 Stack trace: #0 /var/www/html/tests/appt/arian-api-book.php(69): JsonRpcClient->__call(‘book’, Array) #1 {main} thrown in /var/www/html/tests/appt/JsonRpcClient.php on line 57

Any idea what the issue is here?
Code attached. i left out our keys/user/pass but let me know if that is needed to help debug the issue (i assume it isn’t needed if the credentials im using already works for other API requests in the same script).

Main booking part of the code looks like:

$eventId=1;
$unitId=4; //This unit id #4 is ‘Service Provider #3’ in my account/company ‘arian’.
$date=‘2019-11-18’;
$time=‘08:00:00’;
$clientData = array(
‘name’ => ‘ArianBooking OverAPI (PID: 202, SITE_NUM: XYZ202)’,
‘email’ => ‘arian.hojat@acurian.com’,
‘phone’ => ‘+12153239000’
);
$additionalFields = array(
‘229a1a5c2ca0afbc93470492ac788b58’ => 1010101,
‘7316e77010f8dd77852bee328c2a0d10’ => ‘SITE_101’
); //^^^additional intake fields to fill in for this booking^^^
$bookingsInfo = $client->book($eventId, $unitId, $date, $time, $clientData, $additionalFields);

Thanks in advance,
Arian

Dmytro Bondarev wrote:

Hi! Please provide raw HTTP request. It looks like you are calling admin API, instead of public.
If you are using admin API you should pass client id.

Arian Hojat wrote:

Hi! Please provide raw HTTP request. It looks like you are calling admin API, instead of public.

Note: Im not using pure raw requests, just the JsonRpcClient.php you guys provide to obfuscate those lower-level details to the coder.
I can show you my connection code which I copied from your docs api guide…

If you are using admin API you should pass client id.

At the time, I didn’t know there was 2 separate APIs, admin API is vs. the public API. I just pulled the 1st login/token code that i saw on this page (API documentation | SimplyBook.me Online Scheduling).
I see now that page has two types of login upon 2nd review (and I see the services on API documentation | SimplyBook.me Online Scheduling are divided into when to use public vs company administration web services). Sorry that I missed this.

I guess I have some questions…
####################
Question#1:
I assume this is how you get into the admin API is vs the public API based on two sets of code i see on your Guide page.

//Company Admin web-services login/token
$loginClient = new JsonRpcClient(‘https://user-api.simplybook.me’ . ‘/login/’);
$token = $loginClient->getUserToken($company, $user_login, $user_password);

//pubic web-services login/token
$loginClient = new JsonRpcClient(‘https://user-api.simplybook.me’ . ‘/login/’);
$token = $loginClient->getToken($company, $api_key);

I guess you are saying I have to use the public login. That code looks good, yeh?

####################
Question#2:
Even if I use the latter ‘public’ way of getting a token to book an appt, i still get an error:

Fatal error: Uncaught Exception: Request error: Access denied in /var/www/html/tests/appt/JsonRpcClient.php:57 Stack trace: #0 /var/www/html/tests/appt/arian-api-book.php(73): JsonRpcClient->__call(‘book’, Array) #1 {main} thrown in /var/www/html/tests/appt/JsonRpcClient.php on line 57

Why would my access be denied here?

####################

Thanks,
Arian

Arian Hojat wrote:

Dmitry Bondarev wrote:

Hi! Please provide raw HTTP request. It looks like you are calling admin API, instead of public.
If you are using admin API you should pass client id.

Hey, I was able to add some code to the basic JsonRpcClient.php the api docs page provided and I get this Request/Response info if it helps debug:

Request >>>

{“method”:“book”,“params”:[1,4,“2019-11-18”,“08:00:00”,{“name”:“ArianBooking OverAPI (PID: 202, SITE_NUM: XYZ202)”,“email”:"arian.hojat@acurian.com",“phone”:“+12153239000”},{“229a1a5c2ca0afbc93470492ac788b58”:1010101,“7316e77010f8dd77852bee328c2a0d10”:“SITE_101”}],“id”:1}

End Of request >>>
<<< Server response <<

{“error”:{“code”:-32600,“message”:“Access denied”,“data”:null},“id”:“1”}

<<< End of server response

Redmine Admin wrote:

You are getting access denied exception which means you are using wrong authentication method. Please make sure you are using admin APi as described here API documentation | SimplyBook.me Online Scheduling under “User/Admin API (Company administration service) authorization” section.

You may provide us your athorisation RAW HTTP request with headers to see what is wrong.

Arian Hojat wrote:

Redmine Admin wrote:

You are getting access denied exception which means you are using wrong authentication method. Please make sure you are using admin APi as described here API documentation | SimplyBook.me Online Scheduling under “User/Admin API (Company administration service) authorization” section.

You may provide us your athorisation RAW HTTP request with headers to see what is wrong.

Okay i’ll try with the Company Admin service in a bit and let u know what i see (thought I saw an error when i did it that way). Sorry i saw ‘book’ listed under public services so i assumed I should use that but then I see now there are TWO services both called ‘book’, one under the ‘Company public service’ and another one under ‘Company administration service’ on this page API documentation | SimplyBook.me Online Scheduling.
Why are their 2 different methods called ‘book’ that both say they ‘Creates new booking record’?

Arian Hojat wrote:

Here is using the Company admin service …

[15-Nov-2019 21:47:39 UTC] DEBUG…>>Request >>>
{“method”:“book”,“params”:[1,4,“2019-11-18”,“08:00:00”,{“name”:“ArianBooking OverAPI (PID: 202, SITE_NUM: XYZ202)”,“email”:"arian.hojat@acurian.com",“phone”:“+12153239000”},{“229a1a5c2ca0afbc93470492ac788b58”:1010101,“7316e77010f8dd77852bee328c2a0d10”:“SITE_101”}],“id”:1}

End Of request >>>
<<< Server response <<
{“error”:{“code”:-32000,“message”:“Client with given id not found”,“data”:},“id”:“1”}
<<< End of server response <<

[15-Nov-2019 21:47:39 UTC] PHP Fatal error: Uncaught Exception: Request error: Client with given id not found in /var/www/html/tests/appt/JsonRpcClient.php:61
Stack trace:
#0 /var/www/html/tests/appt/arian-api-book.php(84): JsonRpcClient->__call(‘book’, Array)
#1 {main}
thrown in /var/www/html/tests/appt/JsonRpcClient.php on line 61

####################################
Here is the code this is running:

<?php
$loginClient = new JsonRpcClient('https://user-api.simplybook.me' . '/login/');
$token = $loginClient->getUserToken($company, $user_login, $user_password);
echo 'token used for this api session:'.$token.'
'; $client = new JsonRpcClient('https://user-api.simplybook.me' . '/admin/', array( 'headers' => array( 'X-Company-Login: ' . $company, 'X-User-Token: ' . $token ) ), true); $eventId=1; $unitId=4; $date='2019-11-18'; $time='08:00:00'; $clientData = array( 'name' => 'ArianBooking OverAPI (PID: 202, SITE_NUM: XYZ202)', 'email' => 'arian.hojat@acurian.com', 'phone' => '+12153239000' ); $additionalFields = array( '229a1a5c2ca0afbc93470492ac788b58' => 1010101, '7316e77010f8dd77852bee328c2a0d10' => 'SITE_101' ); //^^^additional intake fields to fill in for this booking^^^ $bookingsInfo = $client->book($eventId, $unitId, $date, $time, $clientData, $additionalFields); //fails here var_dump($bookingsInfo);

Arian Hojat wrote:

Eh i changed to use the Company Admin credentials… but looks like im still using the public api book call vs the Company Admin api book call that you recommended…

They have different signatures
Public service:
book($eventId, $unitId, $date, $time, $clientData, $additionalFields);
vs
Company admin service:
book($eventId, $unitId, $clientId, $startDate, $startTime, $endDate, $endTime, $clientTimeOffset, , $count, $batchId, $recurringData)

Again I am wondering why there are 2 different methods, what is the difference when each of them should be used? The former looks simpler so wonder why i can’t use that.
The latter Company Admin call is a bit more complex, like what is the clientId? The docs do not state what it is.

Redmine Admin wrote:

Hi, admin method provide you more flexibility. E.g. you can book anything for any client without providing client login credentials / hash. You can use hidden providers in services.

Arian Hojat wrote:

Redmine Admin wrote:

Hi, admin method provide you more flexibility…

Question#1:
So what is the $clientId param in the company admin web-service?
It doesn’t say here: API documentation | SimplyBook.me Online Scheduling

Question#2:
The public service lets you prefill client name/email/phone and intake-fields with the $clientData and $additionalFields respectively.
Can the Company Admin service do the same? If not, I’d rather use the public service.

Thanks,
Ari

Redmine Admin wrote:

Answer #1:
$clientId is id of client for which you want to add booking

Answer #2:
Yes, you need to add client first and pass its id with admin method. Additional fields can be used here too fo course Company administration service methods - Company administration service methods - SimplyBook.me

Arian Hojat wrote:

Redmine Admin wrote:

Answer #1:
$clientId is id of client for which you want to add booking

Answer #2:
Yes, you need to add client first and pass its id with admin method. Additional fields can be used here too fo course Company administration service methods - Company administration service methods - SimplyBook.me

Honestly I’d rather just use the public method vs the company admin method as I don’t need to call a separate addClient() call with that one (the call is simpler and guessing simpler to debug on potential issues).
Back to my original question, why am I getting an access denied for this?:
“Uncaught Exception: Request error: Access denied in /var/www/html/tests/appt/JsonRpcClient.php:61 Stack trace: #0 /var/www/html/tests/appt/arian-api-book.php(86): JsonRpcClient->__call(‘book’, Array) #1 {main} thrown in /var/www/html/tests/appt/JsonRpcClient.php on line 61”

If you want request+response to help debug, here they are (i figured out a way to also output the true headers as well):

Request >>>
{“method”:“book”,“params”:[1,4,“2019-11-20”,“08:00:00”,{“name”:“ArianBooking OverAPI (PID: 202, SITE_NUM: XYZ202)”,“email”:"arian.hojat@acurian.com",“phone”:“+12153239000”},{“229a1a5c2ca0afbc93470492ac788b58”:1010101,“7316e77010f8dd77852bee328c2a0d10”:“SITE_101”}],“id”:1}
End Of request >>>

^^^ Request Headers ^^^
Content-type: application/json
X-Company-Login: arian
X-User-Token: 1ada7cdc656fdf3f750279ef93e9ab0877905970522f6563d5df36db5a70710e
^^^ End of Headers ^^^

<<< Response <<<
{“error”:{“code”:-32600,“message”:“Access denied”,“data”:null},“id”:“1”}
<<< End of server response <<<

I am using these credentials for this getToken call:
$company = ‘arian’;
$api_key = ‘d335f6…090c88’; //I left out the middle part of the api key to be secure here since I wasnt sure if this Issues area is public. Email me if you want the full api_key I’m using at arian.hojat@acurian.com
$token = $loginClient->getToken($company, $api_key); //the token create for this request was: 1ada7cdc656fdf3f750279ef93e9ab0877905970522f6563d5df36db5a70710e

Note: I think I’m using the right credentials because if I change the $api_key to be something different I then get a ‘Wrong API key’ error, not the current ‘Access Denied’ error.

Thanks,
Arian

Dmytro Bondarev wrote:

With public API you should use public endpoint.
Please make sure that you are using public endpoint.

Arian Hojat wrote:

Dmitry Bondarev wrote:

With public API you should use public endpoint.
Please make sure that you are using public endpoint.

K… in your guide online(API documentation | SimplyBook.me Online Scheduling),
I see this for php code to access the ‘Company public service’ endpoint:

h1. Client API (Company public service) authorization:

h2. Authorization from server side code

h3. Getting the token-key.

$loginClient = new JsonRpcClient('https://user-api.simplybook.me' . '/login/');
$token = $loginClient->getToken(YOUR_COMPANY_LOGIN, YOUR_API_KEY);

h3. Initialization JSON-RPC-client.
$client = new JsonRpcClient('https://user-api.simplybook.me' . '/', array(
    'headers' => array(
        'X-Company-Login: ' . YOUR_COMPANY_LOGIN,
        'X-Token: ' . $token
    )
));

So if my full code is doing that, what is the issue?
It seems like I’m using the public endpoint as Im using the same code above:

$company = 'arian';
$api_key = 'd335f6...090c88';
$loginClient = new JsonRpcClient('https://user-api.simplybook.me' . '/login/');
$token = $loginClient->getToken($company, $api_key);

$client = new JsonRpcClient('https://user-api.simplybook.me' . '/', array(
  'headers' => array(
  'X-Company-Login: ' . $company,
  'X-User-Token: ' . $token
  )
));


Dmytro Bondarev wrote:

At least here you have error:
'X-User-Token: ' . $token

In example 'X-Token: ' . $token
In your code 'X-User-Token: ' . $token

Arian Hojat wrote:

Dmitry Bondarev wrote:

At least here you have error:
'X-User-Token: ' . $token

In example 'X-Token: ' . $token
In your code 'X-User-Token: ' . $token

Wow, that is it :).
Thank you so much for helping me with this. Can close this ticket.