Making API requests

📘

If you're just looking to fetch resource data, please have a look at the ResourceDataClient first. In most cases, there will be a selector available for the resource data you need and it'll give you lots of extra benefits over just making your own API requests.

URLs

To get an API URL you can use the getApiUrl(rel, params) method found on the ComponentContext instance. It will return the URL for any API rel that can be found in the API Discovery and it allows for replacing URL or query parameters via a params object.

let url;

url = context.getApiUrl('VpnUsage')
console.log(url);
// result: "https://portal.ixon.cloud:443/api/vpn-usage"

url = context.getApiUrl('Agent', { publicId: 'ixrouter0001' });
console.log(url);
// result: "https://portal.ixon.cloud:443/api/agents/ixrouter0001"

url = context.getApiUrl('Agent', { publicId: 'ixrouter0001', fields: 'name,publicId' });
console.log(url);
// result: "https://portal.ixon.cloud:443/api/agents/ixrouter0001?fields=name,publicId"
🚧

Available API endpoints in the Simulator's mock data

As of now, only a handful of endpoints are implemented and functional in the Simulator's mock data, and they are provided in the list below. If you need to test endpoints that are not in the list, you will need to use production data in the Simulator. To change this option, what you need to do is simulate your component, click on the gear on the top right of the localhost page, and select the Use platform data option in this image as well as a Company of choice:

Endpoints that work with mock data:

  • Agent
  • AgentAuditLogList
  • AgentVpnUsage
  • DataList
  • DataExport
  • GroupList
  • AgentDataRealTimeWebSocket
  • AgentDataTagList
👍

.accesstoken file: why does it suddenly appear in my project?

While testing and developing, you might see a file called .accesstoken (which is a bearer token) in your components project folder. This file is automatically created the first time an API is called after performing the npx cdk login and npx cdk simulate $my-component command. Instead, if a user is not logged in and running code containing API calls with mock data, then the file will not be created.

Note: even if the code does not display the desired result, the API call will still go through the bearer token creation logic without failing. For this reason, the .accesstoken file will appear anyway.

Headers

On all API requests the Api-Application header is required and for most requests you'll also need an Authorization and Api-Company header. The necessary information to supply these header values can be found on the component context's AppData object.

Example

The example below is based on a possible situation where there is a PLC behind the router that runs an HTTP server which serves a JSON API that has a GET /json-api/v1/logs endpoint. The code example makes use of JavaScript's Fetch API for making HTTP requests.

<template>
  <button @click="readLogs()" :disabled="!server">Read Logs</button>
  <ul v-if="logs">
    <li v-for="log in logs">
      {{ log.text }}
    </li>
  </ul>
</template>

<script>
export default {
  name: 'log-reader',
  props: ['context'],
  data() {
    return { baseUrl: null, logs: null, server: null };
  },
  methods: {
    async readLogs() {      
      if (!this.baseUrl) {
        const url = this.context.getApiUrl('WebAccess');
        const response = await fetch(url, {
          headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + this.context.appData.accessToken.secretId,
            'Api-Application': this.context.appData.apiAppId,
            'Api-Company': this.context.appData.company.publicId,
            'Api-Version': '2'
          },
          body: JSON.stringify({ server: { publicId: this.server.publicId } }),
          method: 'POST',
        })
        .then(res => res.json())
        .catch(error => {
          console.error('Error:', error);
        });
        
        if (response) {
          await fetch(response.data.url, { credentials: 'include' });
          this.baseUrl = response.data.url.slice('/?')[0];
        }
      }
      
      if (this.baseUrl) {
        this.logs = await fetch(this.baseUrl + '/json-api/v1/logs')
          .then(res => res.json())
          .catch(error => {
            console.error('Error:', error);
          });
      }
    }
  },
  created() {
    const client = this.context.createResourceDataClient();
    
    // Queries the "active device" on this page to find its HTTP server
    client.query({
      selector: 'Agent',
      fields: ['servers.publicId', 'servers.type']
    }, result => {
      this.server = result[0].data.servers.find(server => server.type === 'http');
    });
  }
};
</script>

<style scoped></style>