API setup and example

Ok, do you want to add that to the Documentation?

https://docs.suitecrm.com/community/contributing-to-docs/simple-edit/

have done so - thanks for the heads up :slight_smile:

You have edited our community Documentation site so that now it includes that extra step? That’s what I meant, I’m not sure you understood me :slight_smile:

Hello!
I have tried everything suggested in this thread, but I still get a 404 when trying to access the endoint Api/index.php/access_token.
I have tried both from my local and production environments (PHP7.3, HTTPS, v7.11.8).
Curious thing is that API access throught Integromat works fine :thinking:
Any idea on how to proceed?
Thank you,
Guido

PS: I promise that I will update the docs if I find a solution :slightly_smiling_face:

7.11.8 had .htaccess problems.

Make sure you have this fix in place

and then run a Admin / Repairs / Rebuild htaccess

1 Like

Thank you @pgr!

I have implemented the fix, and later updated to 7.11.10, but the API still gives me 404.

Further searching in the forum brought me to the conclusion that the issue could be related to the fact that I use nginx and not Apache, meaning that the htaccess file is not interpreted correctly.

Now my challenge is to find a working nginx configuration for SuiteCRM; I will try first with this suggestion: suiteCRM nginx config

Cheers,
Guido

seems to be not only NGINX issue.
See issue 8251 on Github

Edit:
I have the same problem, didn’t find solution so far.

Edit2:
Here is nginx’s log:

2020/01/12 20:50:01 [error] 27020#27020: *23 open() "/srv/http/example/www/crm/Api/index.php/access_token" failed (20: Not a directory), client: 71.124.78.10, server: example.com, request: "GET /crm/Api/access_token HTTP/2.0", host: "example.com"

Looks weird to have /access_token as a path after index.php. but don’t know PHP and its specs :thinking:

Sorry, just seen this - I did so.
Can someone merge this please?

@murray_greig what is your Github user name? I’m guessing you made the change and Github created the commit in your forked repo, instead of on the main one. So you would still need to create a PR. I can help you but if you tell me where I can go looking for it, that would be helpful. Thanks.

Finally I’ve gotten it to work with Nginx or Apache :slight_smile:

@ coccoinomane
For SCRM 7.11.10 and Nginx web-server try this configuration:

(if it is installed in subdir)

location = /subdir/Api/access_token {    
    try_files $uri $uri/ /subdir/Api/index.php;                            
}            
                                     
location ~ /subdir/Api/V8/(.*?)$ {
   try_files $uri $uri/ /subdir/Api/index.php?$args;
} 

If SCRM installed in root (/) just remove subdir and use root path in the configs above.


There are also considerations to be mention regarding Apache web-server. SCRM’s docs don’t mention requirements to check whether ‘mod_rewrite’ module is installed and activated. So one should check it and enable if needed.
Also, AllowOverride directive in Directory directive for the crm’s path should changed from None to All.


Some notes re Getting Available Resources path from docs

GET {{suitecrm.url}}/Api/V8/meta/swagger.json

This path is incorrect since PHP scripts do not set up router to handle this path. See comment on Github. The correct path is Api/docs/swagger/swagger.json.

1 Like

Cool :sunglasses: , thanks for that info…

Can I ask you to please update our API Documentation? Everybody complains that it is inaccurate or incomplete (it is), but then when they solve their problems they don’t update it… it’s a wiki. And we are a Community maintained product :wink:

https://docs.suitecrm.com/community/contributing-to-docs/simple-edit/

Thanks!

Ok, I will :wink:

@pgr

Everybody complains that it is inaccurate or incomplete (it is), but then when they solve their problems they don’t update it… it’s a wiki.

You should definitely charge them somehow :partying_face:

Edit:
@pgr updated wiki/docs. Pull requests from jt0in3e.

1 Like

After whole night struggling with this same issue I found working solution. Using version 7.11.13
Here is an example:

$url = 'https://your_suite_crm/Api/access_token';
$ch = curl_init($url);
$headers = [
	'Accept: application/vnd.api+json',
	'Content-Type: application/vnd.api+json',
	'cache-control: no-cache'
];
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_HEADER,true);
$post = array(
	"grant_type" => 'client_credentials',
	"client_id" => "yor_client_id",
	"client_secret" => "secret"
);

curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post));
$response = curl_exec($ch);

$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $header_size);
$body = substr($response, $header_size);

curl_close($ch);
print_r($response);
3 Likes

Hi All here,

I am new to suiteCRM here. I am trying to get access to API V8 using postman where I can disable ssl.
Now I can use my localhost url http://localhost/newCRM in the curl url.
Rest everything same. But still I am unable to generate the token…Here is my code

<?php 

$url = 'http://localhost/newCRM/Api/access_token';
$ch = curl_init($url);

$headers = [
    'Accept: application/vnd.api+json',
    'Content-Type: application/vnd.api+json',
    'cache-control: no-cache'
];

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_HEADER,true);

$post = array(
    "grant_type" => 'client_credentials',
    "client_id" => "1cf78634-0fd2-1ca6-432f-5f352d2b3c2b",
    "client_secret" => "Admin@55"
);

curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post));
$response = curl_exec($ch);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $header_size);
$body = substr($response, $header_size);

curl_close($ch);
print_r($response);

I had this working last December and finally got some free time to come back to developing API integration with one of our Drupal based sites. I’m able to pull an access token but the reply is longer than I recall and the token does not seem to be recognized by the server in subsequent requests (mainly trying the refresh call first before diving into CRUD operations).

This is reply I’m getting to pulling a new token:

string(834) "{"token_type":"Bearer","expires_in":3600,"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjZkNTViZTg0YTk0ZmNlMTZlMjA5MDEzMjJkMjg2MTVlZWVjOTQxMzA5NzUyY2NmYzYxZjhlMGFmMWFkNmNlYjkyNTlhYzM5MTNkN2RkY2VhIn0.eyJhdWQiOiJkNDM1MWI4Mi1kOTJjLTVlZTMtMzAwOC01ZGUyZThhN2YwZjYiLCJqdGkiOiI2ZDU1YmU4NGE5NGZjZTE2ZTIwOTAxMzIyZDI4NjE1ZWVlYzk0MTMwOTc1MmNjZmM2MWY4ZTBhZjFhZDZjZWI5MjU5YWMzOTEzZDdkZGNlYSIsImlhdCI6MTU5NzU1MDE0NywibmJmIjoxNTk3NTUwMTQ3LCJleHAiOjE1OTc1NTM3NDcsInN1YiI6IiIsInNjb3BlcyI6W119.xCYuZ9D-w_esshb_D7e3Kh5mL4ZCutrJCnJEte45p6Kfeffjg8fXxuwVGC0rmZiSnz_t1s_9dBDDSvbr4TSbxb3bPvF9GvK4AOpyD1FMqGp4RGSYiUrOu3VlWrjFW2weFiuSow_t6rsixkOZJMG-Ye-SLpktGM_XOmUFRrQzaAi-kN391luv6gGNoFtjrifmN_8Cc-DdmASsJyyNY7WoJxaQZwVSR_NyIDG7yG6_FQa7NOacubH7Zxb5kl7iMXYTd44nxCg_UgCgmxHxQNTwMAl76-_mY07YP00U2_TTJ8UrZKIehTFyz54kyhJ04lHM71lKAzGn8fwvKq27bScqhg"}"

And then when I try and use that to pass through to refresh I get this error:

string(111) "{"error":"invalid_request","message":"The refresh token is invalid.","hint":"Cannot decrypt the refresh token"}"

Any hints or ideas would be much appreciated (in that I’ll document and publish my API example code!)

-dvd

A little more progress if I base64_decode that response I get another json object with a token that i can see in the database – but there appears to be extra garbage at the end:

	$token = json_decode($output);
	print_r($token);

	$access = base64_decode($token->access_token);
	print_r($access);
{"typ":"JWT","alg":"RS256","jti":"66c32674e5bc941feb415b71799fc8623ae701bb0e2e6f5a8a21c83a33dbb32f2cc204d96c97b0ca"}Ș]???
?LX?
    ?YL??MYYL?L?

Will try and extract that jti element and see if I can refresh it

-dvd

Progress! Looks like you need to split out the three fields in there separated by dot (’.’) THEN you can base64 decode to get the field:

Explode access_token
Array
(
    [0] => eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjA2YjBmMjUyYjM0ZWI2ZmYyZTc5MGM0MTUwYTk0MjY0MDM5MGQzYjE3YjU1YzY0NGE2MGFiODNjOWQzMjI3N2U4M2E4ODU4YzI5M2Y2ZjhkIn0
    [1] => eyJhdWQiOiJkNDM1MWI4Mi1kOTJjLTVlZTMtMzAwOC01ZGUyZThhN2YwZjYiLCJqdGkiOiIwNmIwZjI1MmIzNGViNmZmMmU3OTBjNDE1MGE5NDI2NDAzOTBkM2IxN2I1NWM2NDRhNjBhYjgzYzlkMzIyNzdlODNhODg1OGMyOTNmNmY4ZCIsImlhdCI6MTU5NzU5MjI1OCwibmJmIjoxNTk3NTkyMjU4LCJleHAiOjE1OTc1OTU4NTgsInN1YiI6IiIsInNjb3BlcyI6W119
    [2] => BxzLJEqdPVJgYpwIi8HmainFZ3xtmJLEfmiFDvqa_XIVXHoSRFd2xJLGqWGqrdBmqlwLSWkAW1Y5ewe9PVNdVwPp_UiYU0msnKTHMX2Egchd0XFgF0KU7-OUtp-L7itEs4lHI_ya5B2ZKIzn4xfE3d-EfKEo1HpTp8__PMMT88l_s0aaGDmdUFqpK1DQxRiTOdKXw7NjYTegF2eH6sxecj0tbRj3XUr921JmhjxqPu9piN5bg02ylsOLzO3C5ERZfUl1HjweDY8wgycvperpx6igBX2cKB_32WEk2DsWbrRZcuqK5ERdQjYOffRKHHI8v23hs-E6B1o1SkFQFMaPxw
)
base64_decode
{"typ":"JWT","alg":"RS256","jti":"06b0f252b34eb6ff2e790c4150a942640390d3b17b55c644a60ab83c9d32277e83a8858c293f6f8d"}Decoding bearer
stdClass Object
(
    [typ] => JWT
    [alg] => RS256
    [jti] => 06b0f252b34eb6ff2e790c4150a942640390d3b17b55c644a60ab83c9d32277e83a8858c293f6f8d
)
JTI = 06b0f252b34eb6ff2e790c4150a942640390d3b17b55c644a60ab83c9d32277e83a8858c293f6f8d

NOTE: still unable to decrypt refresh token – not sure what I should be passing in – tried both the base64 version and the jti

Thoughts?

-dvd

PS: found this site that can decode the entire response https://jwt.io/ and it verifies the signature using the public key so i know the server is sending a valid token

If you want to refresh token you get, than you should use grant_type password.
When getting the token with grant_type client_credentials, you get only API token, without refresh token.

I am using this code in Codeigniter library to get refreshable token:

		$url = $this->CI->config->item('crmapi_url')."Api/access_token";
		$ch = curl_init($url);
		$headers = [
			'Accept: application/vnd.api+json',
			'Content-Type: multipart/form-data',
			'cache-control: no-cache'
		];
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($ch, CURLOPT_VERBOSE, true);
		curl_setopt($ch, CURLOPT_HEADER,true);
		$post = array(
			"grant_type" => 'password',
			"client_id" => $this->CI->config->item('crmapi_client_id'),
			"client_secret" => $this->CI->config->item('crmapi_oauth_secret'),
			"username" => $this->CI->config->item('crmapi_username'),
			"password" => $this->CI->config->item('crmapi_password')
		);

		curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
		$response = curl_exec($ch);

		$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
		$header = substr($response, 0, $header_size);
		$body = substr($response, $header_size);

		curl_close($ch);

		$res_arr = json_decode($body);
		$this->save_token($res_arr);

		return $res_arr->access_token;

Thanks for the hint! I don’t really understand why username/password is required in the first place – literally every other API I use can work with simple API key + secret.

I personally like this approach, because it allows people to use third party apps (mobile applications/browser extensions and such) without having specific/new passwords.