Skip to content

🗄️ Airtable API

Typ: REST API
Auth: API Key / OAuth 2.0
Status: ✅ Marktführer


Übersicht

Airtable als flexible Datenbank für: - Mieterverwaltung - Objektdaten - Wartungshistorie - CRM-Funktionen


API Endpoints

Methode Endpunkt Beschreibung Cache TTL
GET /api/airtable/bases Alle Bases 1h
GET /api/airtable/bases/:id/tables Tabellen einer Base 30min
GET /api/airtable/:baseId/:tableId Records abrufen 1min
GET /api/airtable/:baseId/:tableId/:recordId Einzelner Record 1min
POST /api/airtable/:baseId/:tableId Record erstellen -
PATCH /api/airtable/:baseId/:tableId/:recordId Record aktualisieren -
DELETE /api/airtable/:baseId/:tableId/:recordId Record löschen -
GET /api/airtable/:baseId/:tableId/search Suche/Filter 1min

Airtable API Beispiel

const AIRTABLE_API = 'https://api.airtable.com/v0';

interface AirtableRecord<T> {
  id: string;
  createdTime: string;
  fields: T;
}

interface Tenant {
  Name: string;
  Email: string;
  Unit: string[];
  RentAmount: number;
  ContractStart: string;
  ContractEnd?: string;
  Status: 'Active' | 'Terminated' | 'Pending';
}

async function getTenants(baseId: string, tableId: string): Promise<AirtableRecord<Tenant>[]> {
  const response = await fetch(
    `${AIRTABLE_API}/${baseId}/${tableId}?filterByFormula={Status}='Active'`,
    {
      headers: {
        'Authorization': `Bearer ${process.env.AIRTABLE_API_KEY}`,
        'Content-Type': 'application/json'
      }
    }
  );

  const data = await response.json();
  return data.records;
}

async function createTenant(baseId: string, tableId: string, tenant: Partial<Tenant>) {
  const response = await fetch(`${AIRTABLE_API}/${baseId}/${tableId}`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.AIRTABLE_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      fields: tenant
    })
  });

  return response.json();
}

async function updateTenant(baseId: string, tableId: string, recordId: string, updates: Partial<Tenant>) {
  const response = await fetch(`${AIRTABLE_API}/${baseId}/${tableId}/${recordId}`, {
    method: 'PATCH',
    headers: {
      'Authorization': `Bearer ${process.env.AIRTABLE_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      fields: updates
    })
  });

  return response.json();
}

Filter & Sortierung

// Airtable Formula Syntax
const filters = {
  // Aktive Mieter
  active: "filterByFormula={Status}='Active'",

  // Miete > 1000€
  highRent: "filterByFormula={RentAmount}>1000",

  // Verträge die bald enden (30 Tage)
  expiring: "filterByFormula=AND({ContractEnd}!='',{ContractEnd}<=DATEADD(TODAY(),30,'days'))",

  // Suche nach Name
  byName: (name: string) => `filterByFormula=FIND('${name}',{Name})>0`,

  // Sortierung
  sort: "sort[0][field]=RentAmount&sort[0][direction]=desc"
};

Webhook für Änderungen

// Airtable Webhook (via Automation)
app.post('/webhooks/airtable', async (req, res) => {
  const { base, table, record, action } = req.body;

  switch (action) {
    case 'create':
      await syncNewTenant(record);
      break;
    case 'update':
      await updateLocalCache(record);
      break;
    case 'delete':
      await removeFromCache(record.id);
      break;
  }

  res.sendStatus(200);
});

Umgebungsvariablen

# Airtable
AIRTABLE_API_KEY="pat..."
AIRTABLE_BASE_ID="app..."

# Table IDs
AIRTABLE_TENANTS_TABLE="tbl..."
AIRTABLE_PROPERTIES_TABLE="tbl..."
AIRTABLE_CONTRACTS_TABLE="tbl..."

Rate Limits

Plan Limit
Free 5 req/sec
Pro 5 req/sec
Enterprise 50 req/sec

Marktführer • Flexible Schema • 5 req/sec