ninox API query Endpoint URI Encoding

Post Reply
User avatar
bkromer
Member
Posts: 34
Joined: Thu Jul 11, 2019 10:41 am
Location: Germany

ninox API query Endpoint URI Encoding

Post by bkromer » Tue Jun 16, 2020 11:25 am

I try to make use of the query endpoint of the ninox API.https://ninox.com/de/manual/ninox-api/rest-api

Code: Select all

function verknuepfen(){
					var url = "https://api.ninoxdb.de/v1/teams/uvG2423sCarz7twsCfQ/databases/e5341uvc8plac1/query"; 
					var key = "myToken";
					var json = new ByteArray("{\"Query\":\"1 + 2\"}", "UTF-8");	
					var theHTTP = new HTTP( HTTP.SSL );
					theHTTP.authScheme = HTTP.OauthAuth;
					theHTTP.authorization = "Bearer "+key;	
					theHTTP.url = url;
			  		theHTTP.setPostData( json,"application/json" );
					theHTTP.post();
				
					while( !theHTTP.waitForFinished( 3 ) )
					  {
					       job.log( 1, "API CALL IN PROGRESS!" );
					  } 
						
					if( theHTTP.finishedStatus == HTTP.Ok && theHTTP.statusCode == 200 )
					  {							
							job.log(1,"API CALL successfull RESPONSE: "+theHTTP.getServerResponse().toString( "UTF-8" ));
					  }
					else
					{
						job.log(1,"API CALL Failed:  "+theHTTP.getServerResponse().toString( "UTF-8" )+ "  Status Code: "+theHTTP.statusCode.toString( "UTF-8" ))
					}
	}
verknuepfen()
The response I get is "API CALL Failed: {"message":"Query not provided"} Status Code: 400".
In the Docs they say ".....The query parameter must be escaped with all URI component encoding methods...." but how can I do that in Enfocus Switch".

Can somebody help?
Thanks in Advance
Benjamin Kromer

mkayyyy
Member
Posts: 26
Joined: Mon Nov 21, 2016 6:31 pm
Location: UK

Re: ninox API query Endpoint URI Encoding

Post by mkayyyy » Tue Jun 16, 2020 7:28 pm

You can use the encodeURIComponent static function to do this

Code: Select all

HTTP.encodeURIComponent("{\"Query\":\"1 + 2\"}");

freddyp
Advanced member
Posts: 495
Joined: Thu Feb 09, 2012 3:53 pm

Re: ninox API query Endpoint URI Encoding

Post by freddyp » Wed Jun 17, 2020 8:29 am

I think your problem is related to the fact that you create a ByteArray that you use in setPostData. What is expected there is a JSON string. You will have to do something like this:

Code: Select all

var queryObject = {};
queryObject.Query = "here comes the query";
var queryJSON = JSON.stringify(queryObject);
...
theHTTP.setPostData( queryJSON, "application/json");
...

User avatar
bkromer
Member
Posts: 34
Joined: Thu Jul 11, 2019 10:41 am
Location: Germany

Re: ninox API query Endpoint URI Encoding

Post by bkromer » Tue Jun 30, 2020 4:39 pm

Thank you for your answers.


When I try mkayyyy´s "the encodeURIComponent" thing:

Code: Select all

function jobArrived( s : Switch, job : Job )
{
	var toMail = "asdadads@asdasdasdasd.de";
	var fromMail = "asdadsasd@asdasdads.de";
	var key = "asdasdadsadsasdasd";
	var url = "https://api.ninoxdb.de/v1/teams/asdasdadsassdasdasdasdc/databases/asdasdasdasdasd/query";	
	
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	
	var theHTTP = new HTTP( HTTP.SSL );
	theHTTP.encodeURIComponent("{\"query\": \"sendEmail({from: \""+fromMail+"\",to: \""+toMail+"\",subject: \"TEST \",text: \"TEST\"})\"}"); 
	theHTTP.authScheme = HTTP.OauthAuth;
	theHTTP.authorization = "Bearer "+key;	
	theHTTP.url = url;
	theHTTP.post();
	while( !theHTTP.waitForFinished( 3 ) )
	  {
	       job.log( 1, "API CALL IN PROGRESS!" );
	  } 
		
	if( theHTTP.finishedStatus == HTTP.Ok && theHTTP.statusCode == 200 )
	  {	
		job.log(1,"API CALL successfull RESPONSE: "+theHTTP.getServerResponse().toString( "UTF-8" ));
	  }
	else
	 {
		job.log(3,"API CALL Failed:  "+theHTTP.getServerResponse().toString( "UTF-8" )+ "  Status Code: "+theHTTP.statusCode.toString( "UTF-8" ));
	 }
}
I get an error: "Error in line 13 of script : 'encodeURIComponent' undefined or not a function".

I also tried the querObject thing freddyp:

Code: Select all

function jobArrived( s : Switch, job : Job )
{
	var toMail = "asdadads@asdasdasdasd.de";
	var fromMail = "asdadsasd@asdasdads.de";
	var key = "asdasdadsadsasdasd";
	var url = "https://api.ninoxdb.de/v1/teams/asdasdadsassdasdasdasdc/databases/asdasdasdasdasd/query";	
	
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	
	var theHTTP = new HTTP( HTTP.SSL );
	theHTTP.authScheme = HTTP.OauthAuth;
	theHTTP.authorization = "Bearer "+key;	
	theHTTP.url = url;
	var queryObject = {};
	queryObject.Query = "{\"query\": \"sendEmail({from: \""+fromMail+"\",to: \""+toMail+"\",subject: \"TEST \",text: \"TEST\"})\"}";
	var queryJSON = JSON.stringify(queryObject);
	theHTTP.setPostData( queryJSON, "application/json");	
	theHTTP.post();
	while( !theHTTP.waitForFinished( 3 ) )
	  {
	       job.log( 1, "API CALL IN PROGRESS!" );
	  } 
		
	if( theHTTP.finishedStatus == HTTP.Ok && theHTTP.statusCode == 200 )
	  {	
		job.log(1,"API CALL successfull RESPONSE: "+theHTTP.getServerResponse().toString( "UTF-8" ));
	  }
	else
	 {
		job.log(3,"API CALL Failed:  "+theHTTP.getServerResponse().toString( "UTF-8" )+ "  Status Code: "+theHTTP.statusCode.toString( "UTF-8" ));
	 }
}
I get an error: "Error in line 25 of script : No matching slot found_ available overloads are:; void SHTTP::setPostData(Utility8::SByteArray_QString); "

When I run my script

Code: Select all


function jobArrived( s : Switch, job : Job )
{
	var toMail = "asdadads@asdasdasdasd.de";
	var fromMail = "asdadsasd@asdasdads.de";
	var key = "asdasdadsadsasdasd";
	var url = "https://api.ninoxdb.de/v1/teams/asdasdadsassdasdasdasdc/databases/asdasdasdasdasd/query";	
	
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	
	var mailData = new ByteArray("{\"query\": \"sendEmail({from: \""+fromMail+"\",to: \""+toMail+"\",subject: \"TEST \",text: \"TEST\"})\"}" , "UTF-8"); // , "UTF-8"
	var theHTTP = new HTTP( HTTP.SSL );
	theHTTP.authScheme = HTTP.OauthAuth;
	theHTTP.authorization = "Bearer "+key;	
	theHTTP.url = url;
	theHTTP.setPostData( mailData,"application/json" );
	theHTTP.post();
	while( !theHTTP.waitForFinished( 3 ) )
	  {
	       job.log( 1, "API CALL IN PROGRESS!" );
	  } 
		
	if( theHTTP.finishedStatus == HTTP.Ok && theHTTP.statusCode == 200 )
	  {	
		job.log(1,"API CALL successfull RESPONSE: "+theHTTP.getServerResponse().toString( "UTF-8" ));
	  }
	else
	 {
		job.log(3,"API CALL Failed:  "+theHTTP.getServerResponse().toString( "UTF-8" )+ "  Status Code: "+theHTTP.statusCode.toString( "UTF-8" ));
	 }
}
I get "API CALL Failed: {"message":"Internal Server Error"} Status Code: 500"
But I get a response from the server. And I think the problem is related to the query format.

I tried the same query in Python3 and it works perfectly. Well Python is fairly easy.

Code: Select all

import requests as r
import json
token = "asdasdasdasdasdasdasdasdasdasdasd"
fromMail = "asdasdasdasd@asdasdasdasdde"
toMail = "asdasdads@asdasdasdads.de"
url = "https://api.ninoxdb.de/v1/teams/asdasdasdasd/databases/asdasdasd/query"
query = {'query': 'sendEmail({from: "'+fromMail+'",to: "'+toMail+'",subject: "TEST ",text: "TEST "})'}

re = r.post(url,json=query,headers={'Authorization': 'Bearer '+token,'Content-Type': "application/json"})
jsondict = re.json()
print(re.headers)
print(re.status_code)
print(jsondict)
I get an Status Code of 200 and the email is delivered.
There must be a way to make this work in Javascript also in this old Version.
Benjamin Kromer

Padawan
Advanced member
Posts: 262
Joined: Mon Jun 12, 2017 8:48 pm
Location: Belgium
Contact:

Re: ninox API query Endpoint URI Encoding

Post by Padawan » Tue Jun 30, 2020 7:08 pm

The ninox api documentation mentions that executing a script can be done both using the GET method and using the POST method.

The uri encoding part is mentioned in the documentation with the GET example, and it seems logic to me that it is only relevant for GET requests because in GET requests parameters are passed via URL.

The code you mention with "when I run my script" seems ok for me, although it is hard to check without actually being able to run the code. So I don't know what's wrong there.

Maybe it is worth it to try the GET method? Think it should be something like this:

Code: Select all

function jobArrived( s : Switch, job : Job )
{
	var toMail = "asdadads@asdasdasdasd.de";
	var fromMail = "asdadsasd@asdasdads.de";
	var key = "asdasdadsadsasdasd";
	var url = "https://api.ninoxdb.de/v1/teams/asdasdadsassdasdasdasdc/databases/asdasdasdasdasd/query";	
	
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// String method
	var mailData = new ByteArray("{\"query\": \"sendEmail({from: \""+fromMail+"\",to: \""+toMail+"\",subject: \"TEST \",text: \"TEST\"})\"}" , "UTF-8"); // , "UTF-8"
	
	/*	
	// queryobject method (the content of mailData should be identical using the string method or the queryobject method. The queryobject method is just a bit more readable
	var mailDataObj = {};
	var sendMailObj = {"from" : fromMail, "to" : toMail, "subject" : "TEST", "text" : "TEST"};
	mailDataObj.query = "sendEmail(" + JSON.stringify(sendMailObj) + ")"; // If it wasn't for the sendEmail() thing we could have done the queryobject method with a lot less lines
	var mailData = new ByteArray(JSON.stringify(mailDataObj));
	*/
		
	var theHTTP = new HTTP( HTTP.SSL );
	theHTTP.authScheme = HTTP.OauthAuth; // Maybe this can be ommited or replaced with theHTTP.authScheme = HTTP.ProprietaryAuth;
	theHTTP.authorization = "Bearer "+key;	
	theHTTP.url = url;
	theHTTP.addParameter("query", HTTP.encodeURIComponent(mailData))
	theHTTP.get();
	while( !theHTTP.waitForFinished( 3 ) )
	  {
	       job.log( 1, "API CALL IN PROGRESS!" );
	  } 
		
	if( theHTTP.finishedStatus == HTTP.Ok && theHTTP.statusCode == 200 )
	  {	
		job.log(1,"API CALL successfull RESPONSE: "+theHTTP.getServerResponse().toString( "UTF-8" ));
	  }
	else
	 {
		job.log(3,"API CALL Failed:  "+theHTTP.getServerResponse().toString( "UTF-8" )+ "  Status Code: "+theHTTP.statusCode.toString( "UTF-8" ));
	 }
}
bkromer wrote:
Tue Jun 30, 2020 4:39 pm
Well Python is fairly easy.
That depends on what you're used to :)
I personally find javascript (even legacy Switch javascript) easier then python :)
(Mostly because the only python development project I did was 8-10 years ago )

User avatar
bkromer
Member
Posts: 34
Joined: Thu Jul 11, 2019 10:41 am
Location: Germany

Re: ninox API query Endpoint URI Encoding

Post by bkromer » Wed Jul 01, 2020 9:24 am

You are totally right with what u said. GET Method when the query is in the URL and it needs to be URI Encoded.
This also means I don't need URI Encoding when I have the query in the request body.
I tried it via GET-Method as URL query and got "null" as a server response.

But I managed to get the post body method to work:

Code: Select all

function jobArrived( s : Switch, job : Job )
{
	var key = "asdasdadasdasdasd";
	var url = "https://api.ninoxdb.de/v1/teams/asdasdasd/databases/asdadsads/query";	
	var query = new ByteArray("{\"query\":\"1+2\"}"); 
	var theHTTP = new HTTP( HTTP.SSL );
	theHTTP.authScheme = HTTP.OauthAuth;
	theHTTP.authorization = "Bearer "+key;	
	theHTTP.url = url;
	theHTTP.setPostData( query,"application/json" );
	theHTTP.post();
	while( !theHTTP.waitForFinished( 3 ) )
	  {
	       job.log( 1, "API CALL IN PROGRESS!" );
	  } 
		
	if( theHTTP.finishedStatus == HTTP.Ok && theHTTP.statusCode == 200 )
	  {	
		job.log(1,"API CALL successfull RESPONSE: "+theHTTP.getServerResponse().toString( "UTF-8" ));
	  }
	else
	 {
		job.log(3,"API CALL Failed:  "+theHTTP.getServerResponse().toString( "UTF-8" )+ "  Status Code: "+theHTTP.statusCode.toString( "UTF-8" ));
	 }
}

As the queries getting more complex I am getting the status code 500 again but this might only be a formatting problem.
Thanks a lot for your help.
Benjamin Kromer

User avatar
bkromer
Member
Posts: 34
Joined: Thu Jul 11, 2019 10:41 am
Location: Germany

Re: ninox API query Endpoint URI Encoding

Post by bkromer » Thu Jul 09, 2020 1:22 pm

Today I had a meeting with a Ninox Developer. Here is the Solution. Maybe this helps somebody else too. :)

Code: Select all

function jobArrived( s : Switch, job : Job )
{
	var key = "asdasdasdasdasdadsadsasdasdad";
	var url = "https://api.ninoxdb.de/v1/teams/asdadsadsads/databases/asdasdadsasdasdasd/query"; 
	var query = new ByteArray(JSON.stringify({ 
		"query": "sendEmail({ from: \"asd@asd.de\", to: \"dsa@dsa.de\", subject: \"Hello\", text: \"Hola!\" })"
	}))

	var theHTTP = new HTTP( HTTP.SSL );
	theHTTP.authScheme = HTTP.OauthAuth;
	theHTTP.authorization = "Bearer "+key;	
	theHTTP.url = url;
	theHTTP.setPostData( query,"application/json" );
	theHTTP.post();
	while( !theHTTP.waitForFinished( 3 ) )
	  {
	       job.log( 1, "API CALL IN PROGRESS!" );
	  } 
	if( theHTTP.finishedStatus == HTTP.Ok && theHTTP.statusCode == 200 )
	  {	
		job.log(1,"API CALL successfull Code: "+theHTTP.statusCode +", RESPONSE: "+theHTTP.getServerResponse().toString( "UTF-8" ));
	  }
	else
	 {
		job.log(3,"API CALL Failed:  "+theHTTP.getServerResponse().toString( "UTF-8" )+ "  Status Code: "+theHTTP.statusCode.toString( "UTF-8" ));
	 }
}
The only thing that he could not tell me was how to send Mails with attachments. Wich is also possible in Ninox, but it's unclear if it works over the API. It's not documented.
As I don't know in which format the file has to be I tried this:

Code: Select all

function jobArrived( s : Switch, job : Job )
{
	var key = "asdasdasasdasdasdadsadsadsads";
	var url = "https://api.ninoxdb.de/v1/teams/asdasdasdadasd/databases/asdadsadadsasd/query";  
	var file = File.readByteArray( job.getPath() ) 
	var query = new ByteArray(JSON.stringify({ 
		"query": "sendEmail({ from: \"asd@asd.de\", to: \"dsa@dsa.de\", subject: \"Hello\", text: \"Hola!\",attachments:"+file+" })"
	}))

	var theHTTP = new HTTP( HTTP.SSL );
	theHTTP.authScheme = HTTP.OauthAuth;
	theHTTP.authorization = "Bearer "+key;	
	theHTTP.url = url;
	theHTTP.setPostData( query,"application/json" );
	theHTTP.post();
	while( !theHTTP.waitForFinished( 3 ) )
	  {
	       job.log( 1, "API CALL IN PROGRESS!" );
	  } 
	if( theHTTP.finishedStatus == HTTP.Ok && theHTTP.statusCode == 200 )
	  {	
		job.log(1,"API CALL successfull Code: "+theHTTP.statusCode +", RESPONSE: "+theHTTP.getServerResponse().toString( "UTF-8" ));
	  }
	else
	 {
		job.log(3,"API CALL Failed:  "+theHTTP.getServerResponse().toString( "UTF-8" )+ "  Status Code: "+theHTTP.statusCode.toString( "UTF-8" ));
	 }
}
Maybe somebody had a similar thing to do and can help. :?:
Benjamin Kromer

Post Reply