Content is user-generated and unverified.

Generating PDFs from Airtable Using Google Docs & Apps Script

This guide walks through a complete setup that pulls data from Airtable, populates a Google Doc template, and exports a PDF — all automated with Google Apps Script.


How It Works

  1. Airtable holds your data (clients, invoices, certificates, etc.)
  2. A Google Doc acts as your PDF template with placeholder tags
  3. A Google Apps Script fetches records from Airtable via its API, fills the template, and converts it to PDF
  4. The PDF is saved to Google Drive (and optionally emailed or linked back into Airtable)

Step 1 — Set Up Your Airtable Base

  1. Create or open an Airtable base with the data you want in your PDFs (e.g. Name, Date, Course, Score).
  2. Go to Account → API and copy your Personal Access Token.
  3. Note your Base ID (found in the API docs URL: https://airtable.com/appXXXXXXXX/api/docs) and the Table name.

Tip: In Airtable's API docs for your base, you can see the exact field names and example responses. Keep this page open — you'll need it.


Step 2 — Create a Google Doc Template

  1. Create a new Google Doc.
  2. Write your document layout (invoice, certificate, letter, etc.) and insert placeholder tags wherever you want Airtable data inserted. Use double curly braces:
Dear {{Name}},

Thank you for completing {{Course}} on {{Date}}.
Your score was {{Score}}.
  1. Note the Document ID from the URL:
    https://docs.google.com/document/d/DOCUMENT_ID_HERE/edit

Step 3 — Open the Apps Script Editor

  1. In Google Drive, click New → More → Google Apps Script (or open it from inside a Google Sheet via Extensions → Apps Script).
  2. Delete the default myFunction() code.
  3. Give your project a name at the top (e.g. "Airtable PDF Generator").

Step 4 — Write the Script

Paste the following script and fill in your own values:

javascript
// ── CONFIG ──────────────────────────────────────────────
const AIRTABLE_TOKEN   = 'patXXXXXXXXXXXXXX';       // Your Airtable Personal Access Token
const AIRTABLE_BASE_ID = 'appXXXXXXXXXXXXXX';       // Your Base ID
const AIRTABLE_TABLE   = 'Clients';                  // Your table name
const TEMPLATE_DOC_ID  = '1aBcDeFgHiJkLmNoPqRsTuV'; // Your Google Doc template ID
const OUTPUT_FOLDER_ID = '1ZyXwVuTsRqPoNmLkJiHg';   // Google Drive folder ID for PDFs
// ────────────────────────────────────────────────────────

function generatePDFsFromAirtable() {
  const records = fetchAirtableRecords();
  const folder  = DriveApp.getFolderById(OUTPUT_FOLDER_ID);

  records.forEach(record => {
    const fields = record.fields;
    createPDF(fields, folder);
  });
}

// Fetch all records from Airtable
function fetchAirtableRecords() {
  const url = `https://api.airtable.com/v0/${AIRTABLE_BASE_ID}/${encodeURIComponent(AIRTABLE_TABLE)}`;
  const response = UrlFetchApp.fetch(url, {
    headers: { Authorization: `Bearer ${AIRTABLE_TOKEN}` }
  });
  const data = JSON.parse(response.getContentText());
  return data.records;
}

// Copy template, replace placeholders, export as PDF
function createPDF(fields, folder) {
  // Copy the template Doc
  const templateFile = DriveApp.getFileById(TEMPLATE_DOC_ID);
  const fileName     = `${fields['Name'] || 'Document'} - ${fields['Date'] || ''}`;
  const copy         = templateFile.makeCopy(fileName, folder);
  const doc          = DocumentApp.openById(copy.getId());
  const body         = doc.getBody();

  // Replace each placeholder with the Airtable field value
  Object.keys(fields).forEach(key => {
    const value = fields[key] !== undefined ? String(fields[key]) : '';
    body.replaceText(`{{${key}}}`, value);
  });

  doc.saveAndClose();

  // Export as PDF and save to the same folder
  const pdfBlob = copy.getAs('application/pdf').setName(`${fileName}.pdf`);
  folder.createFile(pdfBlob);

  // Delete the temporary Google Doc copy
  copy.setTrashed(true);
}

Step 5 — Get Your Google Drive Folder ID

  1. Open the Google Drive folder where you want PDFs saved.
  2. Copy the ID from the URL:
    https://drive.google.com/drive/folders/FOLDER_ID_HERE
  3. Paste it as OUTPUT_FOLDER_ID in the script.

Step 6 — Authorise and Run

  1. Click Save (disk icon) in the Apps Script editor.
  2. Click Run → generatePDFsFromAirtable.
  3. The first run will ask you to authorise the script — click through the Google permissions screens.
  4. Check your Drive folder. You should see a PDF for each Airtable record.

Useful Additions

Filter to specific records

Add a filterByFormula parameter to only process certain rows (e.g. only records marked "Ready"):

javascript
const url = `https://api.airtable.com/v0/${AIRTABLE_BASE_ID}/${encodeURIComponent(AIRTABLE_TABLE)}?filterByFormula=${encodeURIComponent("{Status}='Ready'")}`;

Send PDFs by email

Add this inside createPDF() after the PDF is created:

javascript
if (fields['Email']) {
  GmailApp.sendEmail(
    fields['Email'],
    'Your document is ready',
    'Please find your document attached.',
    { attachments: [pdfBlob] }
  );
}

Run automatically on a schedule

  1. In the Apps Script editor, click the clock icon (Triggers).
  2. Add a trigger for generatePDFsFromAirtable → Time-driven → e.g. every day at 8am.

Write the PDF link back to Airtable

After creating the PDF file, you can patch the record back:

javascript
function updateAirtableRecord(recordId, pdfUrl) {
  const url = `https://api.airtable.com/v0/${AIRTABLE_BASE_ID}/${encodeURIComponent(AIRTABLE_TABLE)}/${recordId}`;
  UrlFetchApp.fetch(url, {
    method: 'patch',
    contentType: 'application/json',
    headers: { Authorization: `Bearer ${AIRTABLE_TOKEN}` },
    payload: JSON.stringify({ fields: { 'PDF Link': pdfUrl } })
  });
}

Troubleshooting

ProblemFix
"Exception: Request failed for api.airtable.com"Check your token and Base ID. Make sure the token has read access to the base.
Placeholders not replacedDouble-check field names in Airtable match exactly — they're case-sensitive.
PDF is blank or garbledMake sure doc.saveAndClose() runs before the PDF export.
Script times outAirtable returns max 100 records per page. Add pagination using the offset parameter for larger tables.
Authorisation errorRe-run the script and accept all Google permission prompts.

Pagination (for tables with 100+ records)

Airtable paginates at 100 records. Replace fetchAirtableRecords() with:

javascript
function fetchAirtableRecords() {
  let records = [];
  let offset  = null;

  do {
    const url = `https://api.airtable.com/v0/${AIRTABLE_BASE_ID}/${encodeURIComponent(AIRTABLE_TABLE)}`
              + (offset ? `?offset=${offset}` : '');
    const response = UrlFetchApp.fetch(url, {
      headers: { Authorization: `Bearer ${AIRTABLE_TOKEN}` }
    });
    const data = JSON.parse(response.getContentText());
    records = records.concat(data.records);
    offset  = data.offset || null;
  } while (offset);

  return records;
}

Summary

ComponentPurpose
AirtableData source (records + API)
Google DocVisual template with {{placeholders}}
Apps ScriptGlue — fetches, fills, exports
Google DrivePDF storage
Content is user-generated and unverified.
    How to Generate PDFs from Airtable Using Google Apps Script | Claude