Skip to content

Quick Start with REST API

We will show a simple example to interact with TACTIC REST API using Javacript. For an example using pure Javascript API, please look here.

Start up with the TACTIC API quickly

For the purposes of this documentation, we will be using the TACTIC Portal. The URL to access any project in this server will be the of the following format:

Project URL:

https://portal.southpawtech.com/<MY_SITE>/<MY_PROJECT>

where:

  <MY_SITE> will be replaced by your organization code
  <My_PROJECT> will be replaced by the project you wish to access

In this tutorial, we will be using trial site and api_test project. The URL will be:

https://portal.southpawtech.com/trial/api_test/

Start an HTML page

Start a simple HTML page:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <title>Test App</title>
</head>

<body>
    <div id="jobs">Hello, no jobs yet!</div>
</body>

</html>

Setting up the server information

Let's start with defining our server, site, project, user and password information.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <title>Test App</title>
</head>

<body>
    <div id="jobs">Hello, no jobs yet!</div>
    <script>

        let server_url = "https://portal.southpawtech.com"
        let site = "trial"
        let project = "api_test"
        let user = 'trial_api'
        let password = 'tactic123'

        let base_endpoint = server_url+ "/" + site + "/" + project + "/REST";

    </script>

</body>

</html>

Generating an authenticated ticket

In order to access TACTIC, you must have an access ticket. This token is required for any access to a TACTIC server and is issued by the server upon successful authentication.

As a first step, we have to generate an API ticket which will be attached to a user. This API ticket will have execute commands on the TACTIC server as that user. You can either pre-create the ticket on the TACTIC server or you can use the API to generate one.

This method is useful for login screen when a user is asked to authenticate.

This ticket should be stored somewhere safe. For a browser, it is typical to store this in a cookie or local storage object.

With the REST API, get_ticket method, you can generate a new ticket:

        let ticket = ""

        const get_ticket = async () => {
            ticket = await generateTicket();
            return ticket;
        }

        const generateTicket = async() => {
            let kwargs = {
                'login': user,
                'password': password,
            };
            let ticket = call_tactic("get_ticket", kwargs)
            return ticket;
        }

        const get_endpoint = () => {
            return base_endpoint;
        }

Here we are using call_tactic helper function, which takes two arguments: the REST API method and the keywords argument. We will keep using this helper function whenever we need to interact with TACTIC server using REST API.

        const call_tactic = async (method, kwargs) => {

            let data = kwargs

            let url = get_endpoint() + "/" + method

            let headers = {
                "Authorization": "Bearer " + ticket,
                Accept: 'application/json',
            }
            let r = await fetch( url, {
                method: 'POST',
                mode: 'cors',
                headers: headers,
                body: JSON.stringify(data),
            } )

            if (r.status == 200) {
                let ret = await r.json();
                return ret;
            }
            else {
                throw("ERROR: " + r.statusText);
            }

        }

Simple query

The query method will select all the sobjects of the given type:

        getJobs = async () => {
            ticket = await get_ticket()

            //query for a list of jobs
            let search_type = "workflow/job"

            let kwargs = {
                search_type: search_type
            }
            let jobs = await call_tactic("query", kwargs);
            return jobs;

        }
This will return a list of dictionaries containing the information for each sobject.

Displaying the jobs

We will display the jobs in our HTML page. We will only display the code of each job and the job name for now. We will call get_jobs(), which we defined above and update the HTML.

        let jobs = []
        let results = "";

        getJobs().then(result => {
            jobs = result;
            for (i = 0; i < jobs.length; i++) {
                var currJob =  jobs[i];
                results += "Job Code: " + currJob['code'] + '<br/>'
                results += "Job Name: " + currJob['name'] + '<br/>'
                results += "<hr/>"
            }
            document.getElementById('jobs').innerHTML = results;
        }).catch(error => {
            console.log(error); // Error
        });

Here is the whole HTML file:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <title>Test App</title>
</head>

<body>
    <div id="jobs">Hello, no jobs yet!</div>

    <script>

        let server_url = "https://portal.southpawtech.com"
        let site = "trial"
        let project = "api_test"
        let user = 'trial_api'
        let password = 'tactic123'
        let ticket = ""

        let base_endpoint = server_url+ "/" + site + "/" + project + "/REST";

        const get_ticket = async () => {
            ticket = await generateTicket();
            return ticket;
        }

        const generateTicket = async() => {

            let kwargs = {
                'login': user,
                'password': password,
            };

            let ticket = call_tactic("get_ticket", kwargs)
            return ticket;
        }

        const get_endpoint = () => {
            return base_endpoint;
        }



        getJobs = async () => {
            ticket = await get_ticket()

            //query for a list of jobs
            let search_type = "workflow/job"
            let kwargs = {
                search_type: search_type
            }
            let jobs = await call_tactic("query", kwargs);
            return jobs;

        }

        const call_tactic = async (method, kwargs) => {

            let data = kwargs

            let url = get_endpoint() + "/" + method

            let headers = {
                "Authorization": "Bearer " + ticket,
                Accept: 'application/json',
            }
            let r = await fetch( url, {
                method: 'POST',
                mode: 'cors',
                headers: headers,
                body: JSON.stringify(data),
            } )

            if (r.status == 200) {
                let ret = await r.json();
                return ret;
            }
            else {
                throw("ERROR: " + r.statusText);
            }

        }

        let jobs = []
        let results = "";

        getJobs().then(result => {
            jobs = result;
            for (i = 0; i < jobs.length; i++) {
                var currJob =  jobs[i];
                results += "Job Code: " + currJob['code'] + '<br/>'
                results += "Job Name: " + currJob['name'] + '<br/>'
                results += "<hr/>"
            }
            document.getElementById('jobs').innerHTML = results;
        }).catch(error => {
            console.log(error); // Error
        });
    </script>

</body>

</html>

Note

You can try it in jsfiddle.