Using a Third Party API with Wix fetch

Hi everyone,

I hope this post finds you well,

In the current project I’m undertaking, we have to work with an API that gives us data from a software that is used to manage bookings.

We have an account with this software and there is a possibility of accessing our present bookings within the software using their API.

I am having trouble making the API call in the specific format that the software requests it.

My Objective is getting the JSON data as a response to the API Call and hence making some integrations with that specific data in my website, however, to do that I must first make the call correctly.

I am able to supposedly log the call URL correctly in the developer console according to what the external software and what I’ve found at StackOverflow here however, I cannot make the call yet, nor receive any data as a response.

I am not sure if the headers or ‘get’ method is out of place here.

I attach my page code:
*I have replaced my API key with X’s.

import {fetch} from 'wix-fetch';

export function box65_click(event, $w) {

	function formatDate(date) {
		var d = new Date(date),
			month = '' + (d.getMonth() + 1),
			day = '' + d.getDate(),
			year = d.getFullYear();

		if (month.length < 2) month = '0' + month;
		if (day.length < 2) day = '0' + day;

		return [year, month, day].join('-');
	}

	var updated_until = formatDate($w("#datePicker6").value);
	var updated_since = formatDate($w("#datePicker5").value);

	const call = {
		url: 'https://api2.vcita.com/v2/appointments' + '?' + 'updated_since' + '=' + updated_since + 'T00:00:00.000+8:00' + '&' + 'updated_until' + '=' + updated_until + 'T00:00:00.000+8:00',
		headers: {
			'Authorization': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
		}
	};
	console.log(call);

	return fetch(call, {
			method: 'get'
		})
		.then(response => response.json());
}

I appreciate any help I can get with this important issue.

All comments are gladly welcomed!

Thanks in advance,

Sincerely,

Nicolas

Hi Nicolas,

How do you know what the response is? This line of code doesn’t do anything with the response:
.then(response => response.json());
What are you trying to do with the response? If the code succeeds in entering the .then() function, then you’re halfway there. All that’s left is to use the results that are returned.

You can see some simple examples in the the fetch() API .

I hope this helps,

Yisrael

Hi Yisrael,

Thanks for your response,

Defining a Goal for the API:
I took a look into how the results are supposed to be shown (JSON) from the external API. I attach the response of how the response should look like in the following code snippet. It creates one {} section for each specific appointment (in the below code block, there are two appointments), each appointment has a staff member assigned to it, the staff members are also displayed in my database called 'alloperations '.

[
    {
        "id": "dcd17f240492adff",
        "title": "Half Day Laguna Madre Fishing Trip",
        "client_id": "396ls8lh0yv4ehXX",
        "staff_id": "thfa1bzg4qjmsnXX",
    },
    {
        "id": "e1aee88d4921851d",
        "title": "Half Day Laguna Madre Fishing Trip",
        "client_id": "3e3c6lpt76npsrXX",
        "staff_id": "thfa1bzg4qjmoyXX",
    }
]

My objective is getting all the “staff_id” tags from each specific appointment (section of response) and then filtering them against my existing dataset (connected to my database) using the Wix API ‘not’ function to filter out the previously mentioned “staff_id” tags from the dataset.

Essentially, what I’m trying to achieve, is filtering out anyone (any item in the database) who has a specific appointment already assigned to them.

In three “simple” steps:

  1. Making the API call
  2. Get all “staff_id” tags from the JSON response of API call.
  3. Filter (cross filtering-like) using ‘not’ function to filter out any “staff_id” (staff member) that appears in the previous API call response from the dataset.

I browsed over a lot of information here on the forum, the API reference and StackOverflow and so on and so forth, as well as trying out a couple of ideas, but just couldn’t figure out how to complete the program that I have right now.

import {fetch} from 'wix-fetch';

export function box65_click(event, $w) {

	function formatDate(date) {
		var d = new Date(date),
			month = '' + (d.getMonth() + 1),
			day = '' + d.getDate(),
			year = d.getFullYear();

		if (month.length < 2) month = '0' + month;
		if (day.length < 2) day = '0' + day;

		return [year, month, day].join('-');
	}

	var updated_until = formatDate($w("#datePicker6").value);
	var updated_since = formatDate($w("#datePicker5").value);


	const call = {
		url: 'https://api2.vcita.com/v2/appointments' + '?' + 'updated_since' + '=' + updated_since + 'T00:00:00.000+8:00' + '&' + 'updated_until' + '=' + updated_until + 'T00:00:00.000+8:00',
		headers: {
			'Authorization': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
		}
	};
	console.log(call);

	return fetch(call, {
			method: 'get'
		})
		.then(response => response.json());
}

I appreciate any help I can receive regarding this matter, and would really appreciate anyone’s help!

Thank you,

Sincerely!

We are unable to provide full code solutions. Wix provides many resources to help users learn how to get the most out of Wix Code. We encourage users to take advantage of these resources which include video tutorials, full app examples (which can be loaded into the user’s editor), API documentation, and a wealth of articles describing a wide range of topics - from beginner to advance.

You may also want to check out the WixArena - it’s a hub where you can look for Wix Code (and other) experts for hire.

Thanks Yisrael,

I was not aiming for a full code solution, don’t worry about it. I was looking more for some guidance related to how can I get the JSON data from the response and use it.

Do you have any ideas?

Thanks again!

Nicolas,

Here are a couple of articles that might help:

Ok, thanks, I will keep you updated!

Thanks for everything!

Hi @Yisrael(Wix) ,

I have been trying to achieve this feature for my website and have tried different ways of interacting with the response data based on the resources you provided in your last comment on this post, Yisrael, however, I am not yet able to make the call; every time I run this code, it logs “Fetch did not succeed”, meaning that it didn’t make the call properly. (Attached picture)

I have tried to find a way in which it can properly make the call; as of now, I am just requesting for it to log the data in the console, later I will further manipulate the data, however, I must first make the API call.

import {fetch} from 'wix-fetch';


export function box65_click(event, $w) {

	function formatDate(date) {
		var d = new Date(date),
			month = '' + (d.getMonth() + 1),
			day = '' + d.getDate(),
	

		year = d.getFullYear();

		if (month.length < 2) month = '0' + month;
		if (day.length < 2) day = '0' + day;

		return [year, month, day].join('-');
	}

	//export function makeCall (updated_since, updated_until) {
	var updated_until = formatDate($w("#datePicker6").value);
	var updated_since = formatDate($w("#datePicker5").value);

	const call = {
		url: 'https://api2.vcita.com/v2/appointments' + '?' + 'updated_since' + '=' + updated_since + 'T00:00:00.000+8:00' + '&' + 'updated_until' + '=' + updated_until + 'T00:00:00.000+8:00',
		headers: {
			'Authorization': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
		}
	};
	console.log(call);

	return fetch(call, {
			method: 'get'
		})
		.then((httpResponse) => {
			let unavStaff = httpResponse.staff_id;
			if (httpResponse.ok) {
				return httpResponse.json();
			} else {
				return Promise.reject("Fetch did not succeed");
			}
		})
		.then((json) => {
			console.log(json.staff_id);
		})
		.catch((err) => {
			console.log(err);
		});

I am trying to interact with the following JSON Data (response), specifically with the “staff id” fields, hence the “json.staff_id” and “httpResponse.staff_id”

This is not a response I got through my website, it is a sample response I got from the third party API.

        [{
		"id": "dcd17f240492adff",
		"title": "Half Day Laguna Madre Fishing Trip",
		"client_id": "396ls8lh0yv4ehXX",
		"staff_id": "thfa1bzg4qjmsnXX",
	}, {
		"id": "e1aee88d4921851d",
		"title": "Half Day Laguna Madre Fishing Trip",
		"client_id": "3e3c6lpt76npsrXX",
		"staff_id": "thfa1bzg4qjmoyXX",
	}]

I would very much like to be able to make the API call.

I appreciate anybody’s input on this important matter,

Thanks in Advance,

Nicolas

Hi Nicolas,

How did you get the sample response from the third party API? What was the URL? Does it look exactly the same as your fetch URL that is printed out in the console? Wix Code doesn’t do any magic here. All the fetch does is send the URL. If the URL is incorrect, the fetch will fail.

Hey Nicolas,

Below is a gist of my generic code to perform fetch on Wix. This has been tested against Stripe and Sendgrid. Feel free to use it.

Nicely formatted & sharable version: Generic Wix backend 3rd party API call · GitHub

backend/api/base.jsw

import {fetch} from 'wix-fetch';

import {encodeRequestBody} from 'public/utils/http.js';


// NEVER, EVER, EVER, DISCLOSE THIS SECRET KEY BELOW!!!
const YOUR_API_SECRET_KEY = 'FIXME';


/**
 * A private method to perform an HTTP Fetch request towards an API
 * NOTE: This method is not exposed via `export`
 *
 * @param {string} url - API endpoint
 * @param {string} method - 'get' or 'post'
 * @param {Object} data - the data in form of one-level-deep object dictionary
 * @returns {PromiseLike<T> | Promise<T>}
 * @private
 */
async function request(url, method, data) {
 const options = {
  method: method,
  headers: {
   'Content-Type': 'application/x-www-form-urlencoded',
   'Authorization': `Bearer ${YOUR_API_SECRET_KEY}`
  },
  body: encodeRequestBody(data)
 };

 const response = await fetch(url, options);

 if (response.ok) {
  return await response.json();
 }

 return await response.text();
}

/**
 * Perform a GET method on the API with the given data
 *
 * @example
 * import {get} from 'backend/api/base.jsw';
 * get('https://api.example.com/v1/something', {source: 'some_token'})
 *     .then(results => handle(results, ...))
 *     .catch(error => handleError(error, ...));
 *
 * @param {string} url - API endpoint
 * @param {Object} data - the data in form of one-level-deep object dictionary
 * @returns {PromiseLike<T>|Promise<T>}
 */
export async function get(url, data) {
 return await request(url, 'get', data);
}

/**
 * Perform a POST method on the API
 *
 * @example
 * import {post} from 'backend/api/base.jsw';
 * post('https://api.example.com/v1/something', {source: 'some_token'})
 *     .then(results => handle(results, ...))
 *     .catch(error => handleError(error, ...));
 *
 * @param {string} url - API endpoint
 * @param {Object} data - the data in form of one-level-deep object dictionary
 * @returns {PromiseLike<T>|Promise<T>}
 */
export async function post(url, data) {
 return await request(url, 'post', data);
}

public/utils/http.js

/**
 * Encode the key:value object into URI based string
 * i.e. from { key1: 'value1', key2: 'value2' }
 * to 'key1=value1&key2=value2'
 *
 * @param {Object} bodyData - the data in form of one-level-deep object dictionary
 * @returns {string} - the encoded string
 */
export function encodeRequestBody(bodyData) {
 let encoded = '';
 for (let [key, value] of Object.entries(bodyData)) {
   encoded = `${encoded}${key}=${encodeURIComponent(value)}&`;
 }

 return encoded;
}

The problem with your code is that you put the headers inside the call object. Wix’s .fetch() actually works by:

.fetch(url, options)

The options is an object which looks like this:

{
  method: 'get',
  headers: {
    'Content-Type': '<the target content type>',
    'Authorization': 'Bearer <your api key>'
  },
  body: 'key1=value1&key2=value2'
}

Hi Yisrael and Luan,

Thank you for the kind help,

In regards to your comment, Yisrael,

I haven’t been able to have the call as a url, since I cannot figure out how to include the Authorization header inside the call.

I got the sample response from their website in the following “Try it out!” input form.

I did reach out to the software provider and they recommended this Stackoverflow article , as well as the following recommended format for making the call in javascript:

$http.get('https://api2.vcita.com/v2/appointments?updated_since=2013-04-03T00:00:00.000+8:00&updated_until=2017-04-03T00:00:00.000+8:00, { headers: {'Authorization': 'XXXXXXXXXXXXXXXXXXXX'} });

When I log (call, options) as Luan suggested, I get:

{"url":"https://api2.vcita.com/v2/appointments?updated_since=2018-06-05T00:00:00.000+8:00&updated_until=2018-06-13T00:00:00.000+8:00"} {"method":"get","headers":{"Authorization":"XXXXXXXXXXXXXXXXXXX"}}

This is the software providers’ website for this API: http://developers.vcita.com/docs/v2appointments

In regards to your comment, Luan,

I did integrate an options field here in my following new code, however it still gives me “Fetch did not succeed”.

import {fetch} from 'wix-fetch';  

export function box65_click(event, $w){

function formatDate(date) {
 var d = new Date(date),
        month = '' + (d.getMonth() + 1),
        day = '' + d.getDate(),
        year = d.getFullYear();

 if (month.length < 2) month = '0' + month;
 if (day.length < 2) day = '0' + day;

 return [year, month, day].join('-');
}

//export function makeCall (updated_since, updated_until) {
var updated_until = formatDate($w("#datePicker6").value);
var updated_since = formatDate($w("#datePicker5").value);
 

const call = {
  url: 'https://api2.vcita.com/v2/appointments'+'?'+'updated_since'+'='+ updated_since +'T00:00:00.000+8:00'+'&'+'updated_until'+'='+ updated_until + 'T00:00:00.000+8:00',
}

const options = {
      method: 'get',
      headers: {
 'Authorization': "24d4bcf9a068f4c0b7669cfa60219626"},
}
 
            console.log(call, options);
 
return fetch(call, options)
.then( (httpResponse) => {
 //let unavStaff = httpResponse.staff_id;
 if (httpResponse.ok) {
 return httpResponse.json();
    }
 else {
 return Promise.reject("Fetch did not succeed");
    }
  } )
  .then( (json) => {
    console.log(json.staff_id);
  } )
  .catch( (err) => {
    console.log(err);
  } );


//.then(response => console.log(response.json.staff_id));
 
 //.then(response => response.json())
 //.then(json => json.staff_id)
 

}

Thanks for your code Luan, I did look into it, however, some values in my code depend on date pickers and it all has to be triggered on an .onClick event in my scenario, thus I couldn’t implement it for this specific function, however I will use it on another project while working with Stripe, Thank you so much!!

Thanks for all of your comments, I am still having issues with this feature, I appreciate very much all of your help and suggestions,

Thanks again!

Sincerely,
Nicolas Garza

You could put my code into the Backend and Public folder (in each file there’s a specific place for you to put in).

Then in your page code, import the get or post function to do it. You can look at this link Velo Web Modules: Calling Backend Code from the Frontend | Help Center | Wix.com to find out how to do that.

In regard to your code, it still misses the Token part in Authorization (based on the docs you gave). It should be

'Authorization': 'Token XXXXXXXXXXXXX'

I will Try your solution about the backend code Luan,

The “Token” part of the call did not do any noticeable difference in its performance, but it is something that needs to be taken into account, thanks Luan.

It is needed because the full authorization string required by vCita has to follow that format. The trick is to see how they perform a request in the Request Headers part of your screenshot above.

Every API has their own way of authorizing user. Stripe and Sendgrid use “Bearer” as the keyword. vCita, in this case, uses “Token”. Hence it’s not about the performance, it’s just the requirement of the API.

Thanks Luan,

I wasn’t aware that that was a requirement, Thanks again for everything. I will keep working on it and keep this thread up to date.

Thanks!

Then, three years had already passed…