Integration
Formfeed für Airtable
Eine Airtable-Base ist eine Tabelle mit API und damit eine natürliche Quelle für Dokumente. Die Aktion „Run a script“ ruft die API direkt auf — sie läuft auf den Servern von Airtable, CORS steht also nicht im Weg — und so rendert und archiviert eine Base ihre Rechnungen, Zertifikate und Berichte schon heute.
Keine Erweiterung zu installieren: Ein Automatisierungsskript erledigt es heute. Eine Formfeed-Erweiterung für Airtable ist geplant, noch ohne Datum.
Kostenloser Plan mit 100 Einheiten im Monat, keine Kreditkarte
Ein Dokument pro Datensatz
Auslöser ist ein Datensatz, der eine Ansicht betritt, eine Bedingung oder ein Button; dann die Aktion „Run a script“ mit der Datensatz-ID. Das Rezept Schritt für Schritt, mit Positionen aus einer verknüpften Tabelle, steht in der Dokumentation.
const { recordId } = input.config();
const API_KEY = 'ff_test_…';
const table = base.getTable('Invoices');
const record = await table.selectRecordAsync(recordId);
const number = record.getCellValueAsString('Number');
const response = await fetch('https://api-eu.formfeed.dev/v1/renders', {
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': `airtable-${recordId}-${number}`,
},
body: JSON.stringify({
template: 'invoice-de',
filename: `rechnung-${number}.pdf`,
data: { invoice: { number }, customer: { name: record.getCellValueAsString('Customer') } },
}),
});
const render = await response.json();
if (render.status !== 'succeeded') throw new Error(render.detail ?? `Render is ${render.status}`);
await table.updateRecordAsync(recordId, {
Document: [{ url: render.download_url, filename: `rechnung-${number}.pdf` }],
'Render ID': render.id,
});Das Dokument landet im Datensatz
- Airtable bekommt eine URL und lädt die Datei selbst herunter: Der signierte Link geht direkt ins Attachment-Feld, und der Datensatz behält die Kopie von Airtable.
- Schreiben Sie die Render-ID zusätzlich in ein Textfeld: Ein signierter Link läuft spätestens nach sieben Tagen ab, und ein Aufruf von
GET /renders/{id}stellt einen neuen aus, solange die Datei aufbewahrt wird. - Eigene Kennungen reisen in
metamit und kommen mit jedem Webhook zurück — so findet ein asynchrones Rendering seinen Datensatz wieder.
Eine ganze Ansicht als ein Batch
Ein Skriptschritt darf 50 Anfragen stellen und keine länger als 30 Sekunden, eine Schleife über eine Ansicht ist also die falsche Form. Ein Aufruf des Batch-Endpunkts reiht stattdessen bis zu 1.000 Dokumente ein, auf Wunsch mit einem Zip aller Dokumente. Der Batch meldet jedes Dokument, sobald es fertig ist, an eine Airtable-Automatisierung mit „When webhook received“, die es in seinen Datensatz schreibt; jede Zustellung ist ein Automatisierungslauf Ihres Airtable-Plans. Lange Einzeldokumente nehmen denselben Weg: mode: async und die Webhook-URL. Beide Skripte stehen im Rezept.
Vorher wissenswert
- Airtable-Automatisierungen haben keinen Schlüsselspeicher: Wer die Base bearbeiten darf, liest den Schlüssel. Geben Sie jeder Base einen eigenen mit den kleinstmöglichen Scopes.
- Bauen Sie mit einem Test-Schlüssel: Diese Renderings werden nicht berechnet und die Dateien nach einem Tag gelöscht.
- Ein Idempotency-Key macht Airtables Wiederholungsläufe harmlos — 24 Stunden lang liefert der zweite das erste Dokument, statt erneut zu rendern und zu berechnen.
- In der Scripting-Erweiterung läuft der Code im Browser, und die API weist einen Schlüssel ab, der diesen Origin nicht erlaubt. Dort nehmen Sie
remoteFetchAsync.
Was die Erweiterung ergänzen wird
Geplant, noch ohne Datum: die Felder einer Tabelle in einem Panel einer Vorlage zuordnen, die ausgewählten Datensätze rendern und das Attachment-Feld füllen — das Skript von oben ohne das Skript. Bis es sie gibt, ist das Skript der Weg.
Oder ein Tabellenstapel
Die Ansicht als CSV exportieren und in der App „Batch aus Tabelle“ nutzen: Spalten einmal zuordnen und das Zip herunterladen. In der Base wird dabei nichts gespeichert.