API Flow: Upload image to Airtable, send to Duda, send optimized image file back to your collection

Elizabeth_Fedak Member Posts: 106 MVP
edited January 2022 in Ask a Question

Make life easier for your clients and make their sites faster with optimized images by uploading images to Duda from their Airtable base

In a quest to make a custom widget using 12k-15k records in an Airtable collection as fast as possible and as easy to use as possible, I wrote out a script that uploads images to Duda and sends the Duda image URL back to the base, so it can be used without dealing with the process of uploading the image to Duda yourself and manually grabbing the URL to then paste into Airtable again.

Here's some code you can use if you're tech savvy.

let table = base.getTable("Table 1");
let record = await input.recordAsync('',table).catch()
const imgUrl = record.getCellValue("Attachments")[0].url;

const obj = {}
obj.imgUrl = imgUrl;
obj.id = record.id;
let data = JSON.stringify(obj);

const options = {
    method: 'POST',
    body: data,
    headers: {
         'Content-Type': 'application/json'

let response = await remoteFetchAsync('{YOUR SERVERLESS FUNCTION ENDPOINT}', options);

Step 1: Add a scripting block in your Airtable base (requires a Pro plan)

In your Airtable base, add a new column and use the 'button' field type. Connect it to the scripting app and create a new dashboard for your code. Add this script below. On line 3, replace the word Attachments with the name of your image column where you're uploading images to Airtable. The rest of the code is getting the current base, getting the details for the record in the particular row where you click the button, and grabbing the URL of the image itself and not extra details, like the name of the image.

Then it calls a serverless function that handles the calls to Duda and sends the response back to Airtable. I recommend using Google Cloud Functions for your serverless function because you can up the timeout time if you need to. The upload resource endpoint takes a while because it is making a bunch of versions of the image over at Duda and doesn't send the final image URL back until it's done.

Step 2. Write your serverless function to handle the image upload to Duda and the response to Airtable

* Responds to any HTTP request.
* @param {!express:Request} req HTTP request context.
* @param {!express:Response} res HTTP response context.

const fetch = require('node-fetch');

exports.uploadToDuda = (req, res) => {
    let id = req.body.id;
    let img = req.body.imgUrl;
    let obj = {resource_type: 'IMAGE', src: ''}
    obj.src = img;
    let arr = [];
    arr.push(obj); // Duda needs to be passed an array of objects w the image url and resource type.

    fetch('https://api.duda.co/api/sites/multiscreen/resources/{YOUR SITE ID}/upload', {
        method: 'POST',
        body: JSON.stringify(arr),
        headers: {
             'Content-Type': 'application/json',
             'Accept': 'application/json',
             'Authorization': process.env.DUDA_AUTH
     .then(res => res.json())
     .then(function(data) {
     let newImgURL = data.uploaded_resources[0].new_url;
     let responseObj = {

// I give up on manually spacing this code in the editor here 😅
records: [
    "id": "",
    "fields": {
     "dudaImg": ""
responseObj.records[0].id = id;
responseObj.records[0].fields.dudaImg = newImgURL;
let responseJson = JSON.stringify(responseObj);
let airtableOptions = {
method: 'PATCH',
headers: {
'Authorization': process.env.AIRTABLE_AUTH,
'Content-Type': 'application/json'
body: responseJson
fetch("{YOUR AIRTABLE BASE URL}", airtableOptions)
.catch(err => console.log(err))

This code is going to read the request object from Airtable, get the image URL, upload it to Duda, wait for the NEW URL, then send that back to Duda.

In the GCP function, be sure to set the allUsers permission with the Cloud Function Invoker permission and to set HTTP as the trigger. That's about it! Once the new URL is added to your Airtable base, you can delete that old image in the base to save storage space, or simply leave both there.


Can I use this to upload many images at once? Yes, you will need to write new code that generates the array for multiple images though and gets all of the source URLs. Duda can take up to 10 images at a time with this endpoint. You'll need to make an array of arrays of images and go through each one if there are more than 10 images in a record to be uploaded with a script.

My image didn't upload. Make sure you're using an image with a .jpeg or .png ending. If it's something you added via an Airtable image search rather than uploading an image file to Airtable, it works like 30% of the time. The Duda documentation specifies that you are required to use a valid image URL, so don't use the .attachment Airtable format unless you want to have frequent failure of the function call. Import a real image file.

How can I tell if it's working? First, you'll see the new URL in the table. Second, in GCP, you can add a console.log() statement to the code and check in the logs to see if you get "UPLOADED" in the response object or "NOT FOUND". If you didn't read the previous FAQ item and used an Airtable file with their built-in URL formatting then it's going to be hit or miss, so be sure to use a real image URL.

Can I use this to upload other file types? No, the content import endpoint ONLY works for image files (not PDFs, CSVs, etc).