Q: How to use Coda API in packs? and other simple examples of common tasks

I’m keep trying to get started writing packs, both internal ones, and possible external ones to publish, but I keep getting stopped by really simple blocks that I just can’t figure out, or don’t have the time to figure out.

Can some point to where I can find these, or provide the example on how to these really basic tasks:

  1. Accept a table as parameter for formula/action
    While it’s useful to create formulas that work on a few values, or cells. It’s also really useful to be able to pass a table. Think for example a simple export to a specific file format.
    I could not find a single example of it being done. Is the only way to do it with the Coda API?

  2. Speaking of the Coda API. The documentation shows how to authenticate it, but I couldn’t find a single example of using the Coda API in the a pack. I know it’s being done by many packs, so it must be pretty straight forward, but I can’t even figure out how to import the Coda API, so I’m not sure how to even begin working with it.

Help?

Hi @Ron_Srebro1 - Thanks for reaching out, and sorry to hear about the roadblocks getting in your way. To address your specific questions:

  1. Unfortunately the Packs SDK doesn’t currently allow you to accept an entire table as a parameter. It’s been a common request from Pack makes, but it turns out to be complicated problem to solve and we haven’t tackled it head on yet. Packs like Export Tables instead have the user pass the name of the table as a string and then use the API to fetch the contents, but as @Courtney_Milligan1 can attest this approach has some usability concerns.

  2. As mentioned above, using the Coda API within a Coda Pack has some drawbacks that make it not an ideal experience. Because of this we haven’t created a lot of samples that show this combination. We do though have a small sample that shows how to setup authentication using a Coda API token in a Pack.

In my experience use cases that truly require passing an entire table are rare, and most times there is a way to structure the inputs with StringArray or other parameter types that can meet your needs. I’m happy to dive into your use case further and see if there are workarounds that can be used.

Also - as an example, the doc explorer pack is essentially the Coda api wrapped in a pack

Ya I’ve used the Coda API several times in my packs but it’s always something I try to avoid if possible. The main issue with using it is that there’s about a 1 minute lag in the API being updated after your Coda doc is updated which can lead to unexpected discrepancies in the pack output.

Another issue is that passing the table name in as a string is confusing to users because it means they can’t pass in the actual table object which comes up in auto-complete when they are typing the formula. I usually add custom auto-complete options to my pack parameters where the options come from the tables in the user’s doc to try to mitigate this issue. It would be great if in the future users could pass their table object into packs and then the pack could at least receive the metadata from it (@Eric_Koleda is this an option?)

1 Like

It’s feasible, but not something we’ve implemented yet.

I appreciate you sharing this. Is the code for the Doc Explorer pack available as a sample or open source?

I’m sorry for being dense, but I just need a sample code that goes beyond how to set up the authentication, and actually calls a function from the API.

It’s not open source sorry - but defintiely happy to help answer your questions here specifically as you have them!

It’s really is a simple question.

This is the code snippet to set up authentication for working with coda API

import * as coda from "@codahq/packs-sdk";
export const pack = coda.newPack();

// Per-user authentication to the Coda API, using a token in the Authorization
// header.
// See https://coda.io/developers/apis/v1
pack.setUserAuthentication({
  type: coda.AuthenticationType.CodaApiHeaderBearerToken,

  // Creates the token automatically when the Pack is installed.
  shouldAutoAuthSetup: true,
});

// Allow the pack to make requests to Coda.
pack.addNetworkDomain("coda.io");

But it doesn’t show how to call any API function. Or how to even import the API library.

So really two simple questions (that I feel stupid for not getting myself) :

  1. How do import the coda API?
  2. How do I call a function like listTables. Do I need to make fetch calls? Is there no way to use Coda-JS? coda-js - npm

Yes, you would just make fetch calls to the Coda API like any other API. There is no official JavaScript library for the Coda API, and I don’t believe the coda-js library you pointed to supports the Packs runtime.

Yeah this is one point that tripped me up in the beginning - because the Packs SDK / infrastructure handles so much of the fetch stuff for you (like headers & auth), and because they force you (for legitimate security reasons) to use their own fetch method, any node modules that fetch things will not work (eg API wrappers like the coda one you mentioned).

Did you get this working? Nobody has shared a code snippet with you yet I’m realizing - lmk if that would still be helpful.

Thanks for reply Nick.

A code snippet would be useful.

For some reason there is still no where an example of how to do it anywhere that I could find. It’s like the most kept secret about Coda.

Here’s something from an internal Pack I was working on recently, where I call the API to get analytics about my docs. This is inside a sync table but it’s a similar kind of thing in other places. And you’re correct about all the setup stuff you need up at the top to make the below stuff work:

let docIds = //... a list of doc IDs I already had on hand from earlier in the code

// coda.withQueryParams is a way to safely and reliable build a URL
// with query parameters
let analyticsUrl = coda.withQueryParams(
  "https://coda.io/apis/v1/analytics/docs", // Coda API's base URL for analytics
  {
    docIds: docIds,
    scale: "cumulative",
    limit: 100,
  }
);
// This is the main fetch request where we hit the API endpoint
let analyticsResponse = await context.fetcher.fetch({
  method: "GET",
  url: analyticsUrl,
});
let analytics = analyticsResponse.body.items; // here's where the meat of the data is

You mentioned wanting to get tables in a doc. This code is untested but it would be something like this:

let docId = // a doc ID you probably have the user pass in to the formula
let result = await context.fetcher.fetch({
  url: `https://coda.io/apis/v1/docs/${docId}/tables`,
  method: "GET",
});
let tables = result.body.items;
1 Like

Thanks Nick. This is super helpful

1 Like

Oh, don’t forget to await the context.fetcher.fetch()

(Updated my code to fix)

1 Like