Pack results question

Hello all from the coding Newbie!

I am attempting to fetch the data from the free travelbriefing.org API. The return JSON data is as follows:

“names”: {

    "name": "Netherlands",

    "full": "Kingdom of the Netherlands",

    "iso2": "NL",

    "iso3": "NLD",

    "continent": "EU"

},

"maps": {

    "lat": "52.2129919",

    "long": "5.2793703",

    "zoom": "7"

},

"timezone": {

    "name": "Europe/Amsterdam"

},

"language": [

    {

        "language": "Dutch",

        "official": "Yes"

    }

],

"electricity": {

    "voltage": "230",

    "frequency": "50",

    "plugs": [

        "C",

        "F"

    ]

},

"telephone": {

    "calling_code": "31",

    "police": "112",

    "ambulance": "112",

    "fire": "112"

},

"water": {

    "short": "safe",

    "full": ""

},

"vaccinations": [],

"currency": {

    "name": "Euro",

    "code": "EUR",

    "symbol": "€",

    "rate": "0.92284",

'********************************************************************

I used the following Code to Execute and retrieve the data:

execute: async function (, context) {

  const url = "https://travelbriefing.org/Netherlands?format=json";



  // context.fetcher.fetch allows you to pull in external data, specifying things like the HTTP method and URL.

  

  const response = await context.fetcher.fetch({ method: 'GET', url });

  // The entire body of the response contains the ltext to be returned.

  

  return response.body

},

// In this formula, we're returning a string.

 resultType: coda.ValueType.String,

});
'****************************************
I can build the pack, and add it to a doc, but only the name “Netherlands” appears and I must hover over the word to see the data.

image

Is there a way to break out the data either in the Pack code or on the CODA canvas? The “.” operator is not working on the Coda canvas.

Also, is there a way to add a parameter so that the user can input different countries besides hardcoding it in the URL? The API does not specify parameters, unlike the Sunrise-Sunset pack. Would it be best to build a sync table in this situation to pull in the data?

Thank you in advance.

Not super sure why the . operator wouldn’t be working, you want to reference the fields in the formula editor itself.

It might be because your formula is declared to return a String, instead of a structured object, so the formula editor does not allow referencing the fields of the returned object with the . notation (although surprising that it shows up properly on hover). You can try properly declaring a schema that matches the response body, and replacing the resultType: coda.ValueType.String with a reference to the schema.

As for customizing the country, assuming this is a formula you can definitely add a country parameter to your formula, and even do some fancy stuff like add a preset list of options. Then, use that parameter in your execute to build the URL (replace the “Netherlands” part of the URL with the user-inputted value of the parameter). Depending on how you setup the domain configuration you may need to loosen it (make the domain filter wider, so if you had “Practical travel information for Netherlands - Travelbriefing.org” before you could make it “https://travelbriefing.org”.

1 Like

Thank you for your reply Louca,

I don’t know how to do what you suggest. Is there sample code that you can recommend? I learn from cross-referencing the code examples with the Coda SDK. Also, is there a YouTube video or online course that would provide a description of the steps required, especially for returning responses?

My goals are modest regarding APIs. I’d like to be able to GET data and then reference it in CODA.

Thanks again!

3 Likes

It might be because your formula is declared to return a String, instead of a structured object, so the formula editor does not allow referencing the fields of the returned object with the . notation

@loucadufault is correct, Coda can only “dot” into an object if it knows what fields are there, and to do that you must define a schema and associate it with your formula. A good example of this is the Daylight sample Pack.

3 Likes

As for changing the country, @loucadufault means something like this:

pack.addFormula({
  // ...
  parameters: [
    coda.makeParameter({
      type: coda.ParameterType.String,
      name: "country",
      description: "The country to fetch",
    }),
  ],
  // ...
  execute: async function([country], context) {
    let url = "https://travelbriefing.org/" + country + "?format=json";
    // ...
  }),
});

P.S. - Great work getting as far along as you have! Keep going!

3 Likes

Hi Eric,

The API in the Daylight pack has clearly defined parameters (e.g. lat & lng).

Travelbriefing.org doesn’t define parameters in their API. If I understand correctly, parameters are different from the schema properties.

In the travelbriefing response, there are object strings like “names” which include “name”, “full”, “iso2”:

“names”: {
“name”: “Netherlands”,
“full”: “Kingdom of the Netherlands”,
“iso2”: “NL”,
“iso3”: “NLD”,
“continent”: “EU”
},
Do I then need to define in my schema “names” and the subgroups that I wish to return as strings?

The Daylight results and code are:

“results”: {
“sunrise”: “5:55:34 AM”,
“sunset”: “6:04:30 PM”,
“solar_noon”: “12:00:02 PM”,
“day_length”: “12:08:56”,
“civil_twilight_begin”: “5:35:40 AM”,

Code:
let results = response.body.results;

return {
  daylight: results.day_length + " seconds",
  sunrise: results.sunrise,
  sunset: results.sunset,

I see that daylight, sunrise and sunset are the properties described in the schema.

Am I right to move forward by setting up a schema with properties that I want to return (maybe defined as Country & FullName, for example) , and then changing the code above to - as follows:

let results = response.body.names;

return {
  Country: names.name
  FullName: names.full

Then, would I have to define a response body for every object that I wish to return in addition to “names”? (eg. maps, language, timezones, etc. (e.g. let results = response.body.maps, followed by a return statement.)

I really appreciate your feedback. This is quite challenging!

2 Likes

Travelbriefing.org doesn’t define parameters in their API.

When it comes to APIs “parameters” can take many shapes:

  1. Query parameters, thing things in the URL after the question make.
    ?name=Eric
  2. Post body, the data you send inside the request.
    {"name": "Eric"}
  3. Headers, key-value pairs passed along with the data.
    X-Person-Name: Eric
  4. URL path, segments of the URL that change.
    /person/Eric

In this case the API does have one parameter (one thing you can change), and it’s the country name in the URL (case #4 above).

(Looking at their documentation, it seems what they want you to do is not actually form the URL yourself by inserting a value, but instead lookup the URL from this endpoint: https://travelbriefing.org/countries.json. But you don’t need to worry about that for now.)

If I understand correctly, parameters are different from the schema properties.

Yes! Parameters are the knobs you can turn on the API (the inputs), while schema properties are the bits of data you get from the API (outputs).

Do I then need to define in my schema “names” and the subgroups that I wish to return as strings?

What information to include in your schema, and how to structure it, is completely up to you. You could return just one piece of data or return them all. You could return them exactly as the API does or using completely new property names. That’s the art of Pack building.

I think it’s simplest to start small and build up, so to that end let’s pick something simple, like the name of the country, and only return that property.

let DataSchema = coda.makeObjectSchema({
  properties: {
    name: {type: coda.ValueType.String},
  },
  primary: "name",
});

And then in your formula, after you fetched the response, you’d do this:

let data = {
  name: response.body.names.name,
};
return data;

So in the schema you defined a bucket called name, and in the formula you are filling that bucket with the value from the API. The value we want is here:

{
    "names": {
        "name": "Netherlands",
        // ...
    },
    // ...
}

And to access that we do response.body.names.name.

  • response.body - gets to to the top level of that JSON structure,
  • .names digs into the `names field,
  • .name gets what’s to the right of the name sub-field.

This is certainly a tricky part for a lot of first-time Pack makers, but I hope my explanation helps!

5 Likes

What a great explanation Eric! Thank you so much. I’ll have fun working with it this weekend. :grinning:

1 Like

Hi All,

I was able to build the formula and extract the data from travelbrief.org,! Thank you to Eric, Nick and Louca.

The process taught me the importance of paying close attention to writing code with great specificity related to upper and lower cases and organizing the { , [, and ( correctly.

Also, I copied the postman results at the bottom of the code and commented it out so that I had an easier way to reference the data returned by the API. I could also have had 2 screens open but I decided that the results reference documented on the code itself might be useful in the future.

My next step is to work with an API that requires authorization.

I have one more question in the meantime. With travelbriefing.org, I created 2 formulas in separate packs. What is the trick to combining the 2 formulas in one pack? Is there an example in the SDK?

Thank you, in advance. :grinning:

2 Likes

Congrats on your first Pack @SIMG_ADMIN :tada: Hopefully the first of many!

Writing code is certainly a very exacting process. A lot of computer science teachers use the famous peanut butter and jelly exercise to get students to understand just how exact you have to be. Code formula language is a bit more forgiving, at least when it comes to capitalization.

That’s a great tip regarding post Postman results in your code for referring back.

Regarding two formulas in one Pack, very possible! You only need the import ... and const ... lines once at the top of the file, but can include as many pack.addFormula(...) lines as you want. For example, the Math sample does just that.

Keep up the good work!

3 Likes