API setup and example

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.

What are you getting as a response?
Did you tried to set up a local domain and using this domain in url of your request instead of “localhost/newCRM”?
Did you set up a domain in your suitecrm while installation?

I’m getting both keys with the username/password pull and then can use refresh on it’s own after that with just the client_id version so it’s all good.

(I just cloned the virtual machine of our production instance and spun up a new VM to test against)

I like the approach of giving tools only api keys without having first class user account access to my systems. Like I said, this is probably the first API I’ve encountered that required getting a refreshable key from a set of user credentials versus just being able to use an api-key/secret to manage the access.

In a perfect world your api-keys might have “read-only” access for some cases where you don’t want to allow writes to happen…

Just thinking outloud really – appreciate you guys jumping in!

-dvd

Hi Everyone Here,

I have worked on the issue. If anybody is facing similar kind of issue Please check this link for the solution.

Thank You