When working with the URLs, should I include the # in the variable settings? It seems when I leave it out I get a 404 error. However, when I use it I get a 200 but a bunch of HTML returned output, not the expected records.
In Postman I entered in the Authorization Tab
Type: OAuth 2.0
Add Auth data to: Request Headers
Current Token
Access Token: Available Tokens / Access Token is blank.
Client Secret: The password I created when making the Client ID.
Username: My username to enter SuiteCRM
Password: MY password to enter SuiteCRM
Client Authentication: Send as Basic Auth Header
I have the suitecrm.url & token.url set in the Environment
It would be nice to figure this out and add more clarity to the Postman setup document for others to easily understand and not waste time trying to figure out.
The guide that you are looking at is for SuiteCRM 7.x . It has not been updated yet for SuiteCRM 8.x
If you want to use api in SuiteCRM 8 your urls should include legacy
for example to get access_token your url will be
{{suitecrm.url}}/legacy/Api/access_token
With just the Client ID and Secret I’m getting 401 Unauthorized.
Here’s the debug log from the API test call for modules.
bash-4.4$ tail -f suitecrm.log
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] current_language is: en_us
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Found cache backend SugarCacheMemcache
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Found cache backend SugarCacheZend
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Found cache backend SugarCacheWincache
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Found cache backend SugarCacheAPC
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Found cache backend SugarCacheMemcached
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Using cache backend SugarCacheMemcached, since 900 is less than 1000
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Found cache backend SugarCacheFile
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Found cache backend SugarCachesMash
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Found cache backend SugarCacheRedis
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Found cache backend SugarCacheMemory
Tue Oct 4 06:22:49 2022 [291809][-none-][INFO] Found language file: en_us.lang.php
Tue Oct 4 06:22:49 2022 [291809][-none-][INFO] Found custom language file: en_us.lang.php
Tue Oct 4 06:22:49 2022 [291809][-none-][WARN] Configuration variable date.timezone is not set, guessed timezone UTC. Please set date.timezone="UTC" in php.ini!
Tue Oct 4 06:22:49 2022 [291809][-none-][INFO] Query:SELECT id, name, symbol, conversion_rate FROM currencies WHERE status = 'Active' and deleted = 0
Tue Oct 4 06:22:49 2022 [291809][-none-][INFO] Query Execution Time:9.5844268798828E-5
Tue Oct 4 06:22:49 2022 [291809][-none-][INFO] Query:SELECT category, name, value FROM config
Tue Oct 4 06:22:49 2022 [291809][-none-][INFO] Query Execution Time:0.00018000602722168
Tue Oct 4 06:22:49 2022 [291809][-none-][INFO] Query:SELECT id FROM outbound_email WHERE type = 'system' AND deleted = 0
Tue Oct 4 06:22:49 2022 [291809][-none-][INFO] Query Execution Time:5.6028366088867E-5
Tue Oct 4 06:22:49 2022 [291809][-none-][INFO] Query:SELECT * FROM outbound_email WHERE id = 'a8e374b6-33cc-99d7-2c4e-6328fb6c55f9'
Tue Oct 4 06:22:49 2022 [291809][-none-][INFO] Query Execution Time:0.0001068115234375
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Hook called: ::after_entry_point
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Including module specific hook file for custom/modules
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Including Ext hook file for custom/application
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Custom file is not exists: custom/application/Ext/Api/V8/slim.php
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Custom file is not exists: custom/application/Ext/Api/V8/controllers.php
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Custom file is not exists: custom/application/Ext/Api/V8/factories.php
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Custom file is not exists: custom/application/Ext/Api/V8/globals.php
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Custom file is not exists: custom/application/Ext/Api/V8/helpers.php
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Custom file is not exists: custom/application/Ext/Api/V8/middlewares.php
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Custom file is not exists: custom/application/Ext/Api/V8/params.php
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Custom file is not exists: custom/application/Ext/Api/V8/services.php
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Custom file is not exists: custom/application/Ext/Api/V8/validators.php
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Custom file is not exists: custom/application/Ext/Api/V8/services.php
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Custom file is not exists: custom/application/Ext/Api/V8/beanAliases.php
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Custom routes file is not exists: custom/application/Ext/Api/V8/Config/routes.php
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Hook called: ::server_round_trip
Tue Oct 4 06:22:49 2022 [291809][-none-][DEBUG] Calling MySQLi::disconnect()
You know, after a long evening of going after the API V8, I decided to just start going after GraphQL.
I am using latest version of SuiteCRM, based off of the Bitnami build, using MariaDB (also latest version). I think the issue might have been me installing the newest version of composer.
I decided I had made too many changes and rolled back to base build. I can get to the GraphQL interface. I have not yet generated a token with it so I can auth further requests.
If you have any experience authenticating with GraphQL I would appreciate it. If I find a solution I will update with it here.
That did help, thank you pgr. I was able to setup a php page for testing GraphQL customization The only issue was that you needed to be logged into SuiteCRM and then grab the XSRF-TOKEN as you point out. However for a full customization that sitting outside of the SuiteCRM application I needed to go further and setup full token based authorization for users. That required setting up an oAuth 2.0 client in SuiteCRM, and then connecting to that client for the auth and renewal tokens.
Here is a simple sample HTML page that will retrieve GraphQL data from SuiteCRM using jquery. This sits inside a folder inside the legacy folder in SuiteCRM - /suietcrm/legacy/apidemo/apidemo.html for example. A user that is logged in can click the button and retrieve data. In this example the data retrieved is just user data, but you can use the GraphQL data definitions in SuiteCRM to build your own.
<html>
<head>
<title>
API Demo Page for GraphQL with SuiteCRM - AgonistesGBH
</title>
</head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script>
function getCookie(cname) {
let name = cname + "=";
let ca = document.cookie.split(';');
for(let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
function getGraphData(){
var token = getCookie('XSRF-TOKEN');
console.log(token);
var totalmsg = '';
var operationName = 'getRecordList';
var query = `
query getRecordList($module: String!, $limit: Int, $offset: Int, $criteria: Iterable, $sort: Iterable) {
getRecordList(module:$module, limit:$limit, offset: $offset, criteria: $criteria, sort: $sort) {
id
_id
meta
records
__typename
}
}
`;
var variables = {
'criteria': {
'name': "",
'orderBy': "",
'searchModule': "users",
'sortOrder': "",
'filters': {
'terminal': {
'field': "terminal",
'fieldType': "bool",
'operator': "=",
'values': [1]
}
}
},
'module': 'users',
'limit': 20,
'offset': 0,
'sort': {
'orderBy': "",
'sortOrder': "DESC"
}
};
var r = $.ajax({
async: true,
url: '/api/graphql',
method: 'POST',
ContentType: 'application/json',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json',
'X-XSRF-TOKEN': token
},
data: JSON.stringify({
oerationName: operationName, //'getRecordList',
query: query,
variables: variables
})
}).done(function() {
console.log(r.responseText)
var response = $.parseJSON(r.responseText);
let records = response.data.getRecordList.records;
let dropdown = $('#status');
dropdown.empty();
dropdown.prop('selectedIndex', 0);
totalmsg = totalmsg + '<table><tr><td>Your API Token</td><td colspan=2>' + token +'</td></tr><tr><td colspan=3> </td></tr>';
totalmsg = totalmsg + '<tr colspan=3><td>User List From GraphQL API</td></tr>';
totalmsg = totalmsg + '<tr><td>Key</td><td>ID</td><td>Name</td></tr>';
$.each(records, function(key, entry) {
totalmsg = totalmsg + '<tr><td>' + key + '</td><td>' + entry.attributes.id + '</td><td>' + entry.attributes.name + '</td></tr>';
})
totalmsg = totalmsg + '</table>';
document.getElementById('ApiDisplay02').innerHTML = totalmsg;
});
}
</script>
<body>
<h2>API Demo Page</h2>
<br />
<br />
<div class="newbtn" onclick="getGraphData()" style="width: 110px; height: 45px; line-height: 45px; border-radius: 5px;" id="showdata">Get User Data</div>
<br /><br/>
<div id="ApiDisplay02">Your API return data should appear here...</div>
</body>
</html>