SeaTable Permissions per API
Pattern fuer kontrollierten Mitarbeiter-Zugriff auf eine SeaTable-Base ohne UI-Geklicke. Geschrieben am Erlei-Auftrag (Mai 2026), nutzbar als Vorlage fuer kuenftige Kunden mit aehnlichem Setup.
Was geht und was nicht
| Aufgabe | API verfuegbar | Anmerkung |
|---|---|---|
| Schema lesen (Tabellen, Spalten, Views) | ✓ | via Base-Token + JWT |
| View erstellen / aendern (Filter, Hidden Cols, Sortierung) | ✓ | via Base-Token + JWT |
| User per Email finden (→ @auth.local-ID) | ✓ | Account-Token, /api2/search-user/ |
| User-View-Share setzen (User bekommt nur diese View) | ✓ | Account-Token |
| User-View-Share Permission updaten (r ↔ rw) | ✓ | Account-Token, PUT .../user-view-shares/<share_id>/ — keine DELETE+POST noetig |
| Group-View-Share setzen | ✓ | Account-Token |
| Primary Column / Display Column einer Tabelle aendern | ✗/Workaround | Erste Spalte ist hart gepinnt. Workaround: erste Spalte auf Formula-Typ umstellen, Concat-Formel reinpacken (siehe Sektion „Display-Column im Link-Picker”). |
| Inline neue verlinkte Datensaetze aus einem Form anlegen | ✗ | Forms erlauben nur Auswahl bestehender Records. Workarounds in Sektion „Forms-Limitations”. |
| Spalten-Permissions per Gruppe (Hidden fuer Gruppe X) | ✗ | Nicht in API. Loesung: Hidden Cols in der View, View teilen. |
| User in Workspace einladen | (offen) | im Erlei-Fall war MA schon im Workspace, daher nicht getestet. Vermutlich /api/v2.1/... mit Account-Token. |
| Statistics-Pivot-Sichtbarkeit pro User | (offen) | Hypothese: User-View-Share macht Base zur Whitelist, dann sind Statistics auch ausgeblendet. Beim Test verifizieren. |
Modell verstehen — User-View-Share als Whitelist
SeaTable hat zwei Permission-Mechaniken:
- Base-Sharing (
POST .../user-shares/) — User wird Editor/Viewer der gesamten Base. - User-View-Share (
POST .../user-view-shares/) — User sieht nur die explizit geteilten Views.
Fuer kontrollierten MA-Zugriff ist Variante 2 die richtige. Die View enthaelt:
- Filter = welche Zeilen
- Hidden Columns = welche Spalten
- Permission
roderrw= lesen vs schreiben
Damit ist alles in der View, keine separate “Spalten-Permission-Schicht” noetig.
Token-Typen — wichtig zu unterscheiden
SeaTable hat drei Token-Arten. Jeder funktioniert nur fuer bestimmte Endpoints — Verwechslung gibt 401/404.
| Token-Typ | Wo erstellen | Kann | Header |
|---|---|---|---|
| Base API Token | Base oeffnen → ”…”-Menue → API Token | Daten lesen/schreiben einer Base | Authorization: Token <token> |
| App Access Token (JWT) | abgeleitet aus Base-Token via POST /api/v2.1/dtable/app-access-token/ | Schema/View-Operationen ueber api-gateway | Authorization: Bearer <jwt> |
| Account API Token | Avatar oben rechts → Account Settings → API Tokens | User-Lookup, Sharing, Workspace-Operationen | Authorization: Token <token> |
Goldene Regel: Wenn ein Endpoint /api/v2.1/workspace/... enthaelt → Account-Token. Wenn /api-gateway/api/v2/dtables/... → JWT. Wenn /api/v2.1/dtable/... (Singular) → Base-Token.
Wichtige Endpoints
App-Access-Token aus Base-Token holen
JWT=$(curl -sS 'https://cloud.seatable.io/api/v2.1/dtable/app-access-token/' \
-H "Authorization: Token <BASE_TOKEN>" \
| python3 -c 'import sys,json; print(json.load(sys.stdin)["access_token"])')Antwort enthaelt zusaetzlich dtable_uuid, workspace_id, dtable_name, dtable_server. Die UUID ist persistent — einmal merken.
Schema laden (mit JWT)
curl -sS "https://cloud.seatable.io/api-gateway/api/v2/dtables/<UUID>/metadata/" \
-H "Authorization: Bearer ${JWT}"Liefert komplettes JSON mit allen Tabellen, deren Spalten (mit key, name, type) und Views (mit _id, name, filters, hidden_columns, groupbys, private_for).
View aendern (Filter + Hidden Cols)
VIEW=$(python3 -c "import urllib.parse; print(urllib.parse.quote('Alle Auftraege (offen)'))")
TABLE=$(python3 -c "import urllib.parse; print(urllib.parse.quote('Auftraege'))")
curl -sS -X PUT "https://cloud.seatable.io/api-gateway/api/v2/dtables/<UUID>/views/${VIEW}/?table_name=${TABLE}" \
-H "Authorization: Bearer ${JWT}" \
-H "Content-Type: application/json" \
-d '{
"filters": [{"column_key": "<col-key>", "filter_predicate": "is", "filter_term": "<option-id>"}],
"filter_conjunction": "And",
"hidden_columns": ["<key1>", "<key2>"]
}'Spalten-Keys und Single-Select-Option-IDs aus der Metadata raussuchen. View-Namen mit Umlauten URL-encoden.
User per Email suchen (Account-Token)
curl -sS "https://cloud.seatable.io/api2/search-user/?q=<email-or-substring>" \
-H "Authorization: Token <ACCOUNT_TOKEN>"Antwort: {"users": [{"email": "<id>@auth.local", "contact_email": "<echte-mail>", "name": "..."}]}. Das email-Feld ist die interne ID, die fuer Sharing-Calls als to_user gebraucht wird. Substring-Match — auf contact_email exakt vergleichen, sonst Verwechslung.
User-View-Share anlegen (Account-Token)
curl -sS -X POST "https://cloud.seatable.io/api/v2.1/workspace/<WS_ID>/dtable/<BASE_NAME>/user-view-shares/" \
-H "Authorization: Token <ACCOUNT_TOKEN>" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "permission=rw&to_user=<id>@auth.local&table_id=<table-id>&view_id=<view-id>"Form-Encoded, nicht JSON. permission ist r oder rw. Owner kann sich selbst nicht sharen — gibt 400 "View None cannot be shared with its owner.".
Bestehende Shares listen
curl -sS "https://cloud.seatable.io/api/v2.1/workspace/<WS_ID>/dtable/<BASE_NAME>/user-view-shares/" \
-H "Authorization: Token <ACCOUNT_TOKEN>"Idempotenz-Check vor neuem Anlegen. Listing-Response enthaelt id pro Share — die wird fuer Updates und Deletes gebraucht.
Permission updaten (Account-Token)
curl -sS -X PUT "https://cloud.seatable.io/api/v2.1/workspace/<WS_ID>/dtable/<BASE_NAME>/user-view-shares/<SHARE_ID>/" \
-H "Authorization: Token <ACCOUNT_TOKEN>" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "permission=rw"Body Form-Encoded mit nur permission. Doku: api.seatable.com/reference/updateuserviewshare. Kein DELETE+POST noetig — sauber per PUT. Beispiel-Implementierung als update_share_permission() in ../../runs/2026-04-20-erlei-seatable-scan/scripts/aktiviere_ma.py (eingebaut 2026-05-07 fuer Markus’ rw-Korrektur).
shared_name pro Share setzen (kosmetisches Tile-Label)
curl -sS -X PUT "https://cloud.seatable.io/api/v2.1/workspace/<WS_ID>/dtable/<BASE_NAME>/user-view-shares/<SHARE_ID>/" \
-H "Authorization: Token <ACCOUNT_TOKEN>" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "permission=rw" \
--data-urlencode "shared_name=Aufträge offen"Wichtig — permission muss mitgesendet werden, auch wenn nur shared_name geaendert werden soll. Ohne permission antwortet die API mit 400 "permission invalid". shared_name UTF-8 (Em-Dashes/Umlaute OK), bis ~80 Zeichen visuell sinnvoll. Setzt das Label im „An mich freigegebene Bases”-Tile des Empfaengers.
Use Case: wenn dem User-View-Share-Empfaenger 5+ Sichten der gleichen Base freigegeben sind, sieht er ohne shared_name mehrere Tiles mit identischem Base-Namen — dann ist das Label-Setting Pflicht zur Unterscheidung. Pattern aus Erlei-Run 2026-05-20.
Stolperer
load_view_indexbraucht JWT — der Account-Token greift auf das Schema nicht durch. Das Aktivierungs-Skript loest das ueber eine vorab gespeichertemetadata.json-Datei (Vorbereitungs-Schritt).- View-Namen mit Umlauten zwingend URL-encoden, sonst 404.
- Hidden-Cols-Liste komplett ersetzen — die API merged nicht, sondern uebernimmt die Liste 1:1. Beim Update vorhandene Hidden Cols mitschicken.
- Filter-Term ist die Option-ID, nicht der Label-Name bei Single-Select. Aus
column.data.options[].idraussuchen. - Owner-Token kann sich selbst keine Shares geben — Test mit Owner-Email gibt erwartete 400er.
- Statistics-Pivots sind nicht Teil der View-Liste — separate Sichtbarkeitsregeln (vermutlich „nur Owner” wenn User-View-Share aktiv). Beim ersten echten Test mit Mitarbeiter-Account verifizieren.
forms-Endpoint im api-gateway antwortet nicht wie erwartet — Pull via/api-gateway/api/v2/dtables/<uuid>/forms/liefert kein nutzbares JSON. Forms sind aber von Row-Operationen nicht betroffen (sie haengen amtable_id, nicht an Row-IDs), Schema-Integritaet kann via/metadata/verifiziert werden.
Test-Daten loeschen — Reihenfolge bei verlinkten Tabellen
Wenn ein Kunde eine Test-Phase hatte und vor Live-Betrieb komplett bereinigt werden soll, ist die Lösch-Reihenfolge entscheidend, sonst gibt’s orphaned Links (verwaiste Verlinkungen) oder Schema-Fehler.
Goldene Regel: zuerst Kind-Tabellen, dann Eltern-Tabellen, dann Stammdaten. Konkret:
- Position-/Detail-Tabellen (Positionen, Fremdkosten, Zeiterfassung — alles was per Link auf einen Auftrag zeigt)
- Auftrags-/Vorgangs-Tabelle (Aufträge, Tickets, Projekte — die Eltern-Entitaet)
- Stammdaten (Auftraggeber, Versicherungsnehmer, Besichtigungsorte, Fremddienstleister — referenziert FROM Auftraegen)
Warum: SeaTable’s Row-Delete entfernt nur die Zeile, die Verlinkung (Link-Spalte) wird beim Pull der noch existierenden Eltern-Zeile leer. Wenn du die Eltern-Tabelle zuerst leerst, sind die Kind-Zeilen orphaned aber funktional intakt — Link-Spalten zeigen auf nichts. Saubere Reihenfolge vermeidet das.
API-Mechanik:
# JWT holen wie oben, dann pro Tabelle:
# 1. Alle Row-IDs holen
curl -sS "https://cloud.seatable.io/api-gateway/api/v2/dtables/<UUID>/rows/?table_id=<TABLE_ID>&limit=1000" \
-H "Authorization: Bearer ${JWT}" | jq -r '.rows[]._id'
# 2. Batch-Delete (max 1000 pro Request)
curl -sS -X DELETE "https://cloud.seatable.io/api-gateway/api/v2/dtables/<UUID>/rows/" \
-H "Authorization: Bearer ${JWT}" \
-H "Content-Type: application/json" \
-d '{"table_id": "<TABLE_ID>", "row_ids": ["row1", "row2", ...]}'Skript-Vorlage: ../../runs/2026-04-20-erlei-seatable-scan/scripts/loesche_test_daten.py — implementiert Dry-Run-Modus (zeigt Bestand vor Lauf), automatische Reihenfolge, Verify-Pull nach Lauf. Funktional getestet im Erlei-Run am 2026-05-04 abend (23 Zeilen aus 7 Tabellen, alle leer).
Was Row-Delete NICHT betrifft (bleibt nach Bereinigung intakt):
- Schema (Tabellen, Spalten, Spalten-Typen, Link-Definitionen)
- Views (Filter, Hidden Cols, Sortierung, Groupbys)
user-view-shares(Permissions haengen amview_id)- Forms (haengen am
table_id, nicht an Rows) - Statistics-Pivots (Konfiguration unabhaengig von Daten)
- Link-Formula-Spalten (Summe Stunden etc. — laufen wieder live sobald echte Daten reinkommen)
Multi-User-Risiko: rw-User koennte Filter modifizieren
Problem: Der user-view-share-Mechanismus mit permission=rw erlaubt dem User Schreib-Zugriff auf die Sicht. Was nicht eindeutig dokumentiert ist: kann ein rw-User den Filter der geteilten Sicht aendern? Wenn ja, dann ist eine Zeilen-basierte Sichtbarkeit (z.B. „Mitarbeiter sieht nur eigene Stunden via Bearbeiter include_me”) nicht hart geschuetzt — der User koennte den Filter wegnehmen und alle Zeilen sehen.
Recherche-Stand 2026-05-04:
- SeaTable custom sharing docs — bestaetigt dass andere Tabellen versteckt bleiben, aber kein Statement zu Filter-Modifikation
- Forum-Thread — diskutiert die Mechanik aber liefert keine harte Antwort
Live-Test-Aufgabe (offen, Trigger: erste Mitarbeiter-Registrierung): Mitarbeiter-Account einloggen, in die rw-Sicht gehen, versuchen den Filter abzuschalten oder zu modifizieren. Wenn das geht: rw ist unsicher fuer Zeilen-Schutz.
Mail-Wording-Pattern wenn Sicherheit nicht 100% verifiziert ist:
Statt zusicherndem Wording wie „die Stunden des Owners bleiben fuer den Mitarbeiter unsichtbar” — beschreibendes Wording verwenden: „die Sicht ist so eingestellt, dass sie gefiltert auf seinen Bearbeiter nur seine eigenen Stunden zeigt”. Plus einen Joint-Quickcheck beim ersten Login ankuendigen, bei dem der Berater zusammen mit dem Mitarbeiter die Sicht-Konfiguration einmal verifiziert.
Das schuetzt:
- Den Berater (keine zusicherbaren Aussagen die spaeter zerbrechen koennen)
- Den Kunden (gemeinsamer Quickcheck deckt unentdeckte Schwachstellen sofort auf)
- Die Architektur-Optionalitaet (falls Filter-Modifikation moeglich ist: Architektur-Anpassung von rw → r + separates Eingabe-Form, ohne dass eine peinliche Korrektur-Mail noetig ist)
Architektur-Fallback falls Live-Test ergibt dass Filter modifizierbar ist:
- rw-Sicht zur Datenanzeige → r-Sicht umbauen (Lesen ja, Schreiben nicht)
- Eingabe der Daten ueber ein separates Form das nur per
POST /api-gateway/.../rows/schreibt und implizitBearbeiter = currentUsersetzt - Mitarbeiter sieht nur eigene Daten (gefiltert), schreibt nur eigene Daten (forciert), Filter-Modifikation bringt nichts mehr
Display-Column im Link-Picker — was angezeigt wird ist hart die first column
Befund: SeaTable-Link-Felder zeigen im Picker (in Forms wie auch in Tabellen-Sicht) immer die erste Spalte (primary column) der Ziel-Tabelle. Es gibt keine Picker-eigene „Display-Column”-Konfiguration und keinen API-Call der die Primary Column verschiebt.
Statement im SeaTable-Forum (Karlheinz, offiziell): „The first column is used to identify the row, so it cannot be replaced by other columns in the table.” — Forum-Thread.
Workaround (offiziell unterstuetzt seit Release 3.5): Backup-Spalte anlegen, Werte rueberkopieren, dann erste Spalte auf Formula-Typ umstellen mit Concat-Formel.
# Schritt 1: Backup-Text-Spalte anlegen (POST /columns/)
curl -sS -X POST "https://cloud.seatable.io/api-gateway/api/v2/dtables/<UUID>/columns/" \
-H "Authorization: Bearer ${JWT}" \
-H "Content-Type: application/json" \
-d '{"table_name": "Aufträge", "column_name": "Auftragsnummer (Original)", "column_type": "text"}'
# Schritt 2: Werte aus First-Column in Backup-Spalte kopieren via Batch-Update (PUT /rows/)
# Update-Body: {"table_name": "Aufträge", "updates": [{"row_id": "...", "row": {"Auftragsnummer (Original)": "26-001-ME"}}, ...]}
# Schritt 3: First-Column auf Formula umstellen (PUT /columns/)
curl -sS -X PUT "https://cloud.seatable.io/api-gateway/api/v2/dtables/<UUID>/columns/" \
-H "Authorization: Bearer ${JWT}" \
-H "Content-Type: application/json" \
-d '{
"table_name": "Aufträge",
"op_type": "modify_column_type",
"column": "Auftragsnummer",
"new_column_type": "formula",
"column_data": {"formula": "{Auftragsnummer (Original)} & \" — \" & {Warenart}"}
}'API-Konventionen die nicht in der offiziellen Doku stehen (Erlei-Run 2026-05-20):
- PUT /columns/ braucht zwingend
op_type— sonst HTTP 400 „op_type invalid”. Gueltige Werte u.a.:rename_column,modify_column_type,resize_column,move_column,freeze_column. - Formel kommt in
column_data, nichtnew_column_dataund nichtdata— typischer Fallstrick: API-Aufruf gibt HTTP 200 zurueck (Typ wird umgestellt), aber die Formel landet nicht. Verify-Pull zeigt danndata: {"default_value":"","enable_fill_default_value":false}. - Pflicht-Reihenfolge bei produktiven Daten: Backup zuerst, Typ-Wechsel zuletzt. Beim Typ-Wechsel verschwinden die Werte der First-Column unwiederbringlich — wenn die Backup-Spalte vorher nicht gesetzt ist, sind die Rohdaten weg.
- Formel referenziert Spaltennamen, nicht Keys —
{Spaltenname}mit echtem Display-Namen, Umlaute OK. - Concat-Operator ist
&, nicht+oderconcat(). Beispiel:{ColA} & " — " & {ColB}.
Stolperer:
- Inhalt der ersten Spalte verschwindet beim Typ-Wechsel — Formula-Spalte berechnet sich aus den Inputs, alte Werte sind weg. Vor dem Lauf eine Backup-Spalte anlegen (Text-Spalte mit Inhalt der ersten Spalte rueberkopieren), oder Tabelle vor dem Lauf duplizieren.
- Wirkt global — die neue Display erscheint ueberall wo die Tabelle verlinkt ist (alle Forms, alle Sichten der Eltern-Tabellen, alle Statistics-Pivots). Vor dem Lauf mit dem Kunden bestaetigen, dass die globale Wirkung erwuenscht ist.
- Bestehende Verlinkungen bleiben funktional intakt — Links referenzieren
_id, nicht den Anzeigewert. Aber alle Stellen wo der Anzeige-String benutzt wurde (z.B. Mail-Templates, Exports, Lookup-Felder die auf die first column zeigen) muessen mitgedacht werden. - Ab Release 3.5+ sind Formulas in der ersten Spalte explizit unterstuetzt. In aelteren Versionen ggf. nicht — Server-Version pruefen.
- ⚠ Formula-First-Column bricht Web-Forms (Erlei-Run 2026-05-21): Wenn die Ziel-Tabelle ein Web-Form hat in dem die First-Column als Eingabe-Feld vorkommt, rendert SeaTable das Feld nach dem Typ-Wechsel ohne Input (Label sichtbar, aber kein Textfeld). Markus konnte nach dem Block-C-Lauf keine neuen Auftraege mehr anlegen weil das Form „Auftragserfassung” die First-Column als read-only Formula-Spalte anzeigte. Rollback nach 24h. Pre-Check vor First-Column-Mutation: Forms-Liste der Tabelle pruefen — wenn ein Form existiert in dem die First-Column ein Eingabe-Feld ist, NICHT mutieren, stattdessen Variante mit
display_column_keyin den Link-Spalten der referenzierenden Tabellen waehlen (siehe naechster Block). - Form-Editing-API ist seit v5.3 nicht oeffentlich: weder
/dtable-server/api/v1/dtables/<uuid>/forms/(deprecated, redirect zu API Gateway) noch/api-gateway/api/v2/dtables/<uuid>/forms/(404) noch/api/v2.1/workspace/<ws>/dtables/<uuid>/forms/(404) liefern Form-Metadata. Form-Anpassungen (Feld hinzufuegen/entfernen, Label-Override) gehen nur ueber die SeaTable-UI. Konsequenz: Wenn ein Form ein Feld braucht das umbenannt/ersetzt werden muss, ist das ein UI-Handgriff fuer den Kunden oder Marvin, nicht via API loesbar.
Alternative zu First-Column-Mutation — display_column_key in der Link-Spalte
Seit irgendeinem Release (Stand 2026-05-21 in Cloud aktiv) hat jede Link-Spalte ein Feld display_column_key in ihrem data-Objekt. Default ist "0000" (First-Column der Ziel-Tabelle). Das laesst sich offenbar pro Link-Spalte aendern — heisst der Picker zeigt dann nicht die First-Column sondern eine beliebige andere Spalte als Anzeige-String. Damit wird der Forum-Statement von Karlheinz (Zeile 227 oben) zumindest fuer den Picker-Kontext relativiert — die First-Column bleibt das Row-Identifier-Konzept, aber die Anzeige im Picker ist konfigurierbar.
Saubere Variante (statt First-Column zu Formula machen):
- Eine zusaetzliche Formula-Spalte in der Ziel-Tabelle anlegen, z.B.
Picker-Anzeige={Auftragsnummer} & ", " & {Warenart}. First-Column bleibt unangetastet, Forms bleiben funktional. - In jeder referenzierenden Link-Spalte das
display_column_keyvon0000auf den Key der neuen Formula-Spalte aendern.
API-Pre-Check vor produktivem Einsatz: ob display_column_key ueberhaupt via PUT /columns/ mit op_type=modify_column_metadata (oder aehnlich) modifizierbar ist, war zum 2026-05-21 noch nicht in einem Test-Base verifiziert. Erst in Test-Base klaeren, dann produktiv.
Doku: first-column-features, Release-3.5-Notes.
Forms-Limitations — kein Inline-Create fuer verlinkte Datensaetze
Befund: SeaTable Web-Forms erlauben im Link-Picker keine Anlage neuer Datensaetze. Nur Auswahl bestehender Records. Gilt seit SeaTable 2.0, ist offener Feature-Request.
In der Tabellen-View funktioniert Inline-Create (im Link-Picker-Dropdown gibt’s „neue Zeile erstellen”) — nur Forms haben diese Einschraenkung. Forum-Threads: allow-link-other-record-column-in-forms, creating-new-linked-records-from-searching-existing-records-doesnt-work.
Drei Workarounds, in Reihenfolge der Pragmatik:
| # | Workaround | Aufwand | Trade-off |
|---|---|---|---|
| A | Form weglassen, direkt in der Tabelle erfassen | 0 | UX-Umstellung. In der Tabellen-View geht Inline-Create im Link-Picker. Funktioniert sofort, andere UX als Form. Default-Empfehlung wenn Form nicht zwingend ist. |
| B | Form mit Plain-Text-Feldern + Automation | ~3-4h | Form sammelt Stammdaten als Text-Felder. Trigger row_added mit add_link-Action und Match-Bedingung. Bei No-Match: parallele Python-Action die per API einen neuen Stammdatensatz anlegt und dann verlinkt. Doku: link-entries-automation, automation-actions. |
| C | Custom-Frontend statt SeaTable-Form | ~6-8h | Eigenes Web-Form ausserhalb SeaTable, ruft /rows/-API direkt. Pro Feld erst GET mit Filter, falls leer dann POST in Stammdaten, dann den neuen _id als Link mitschreiben. Sauberste UX, aber Wartung. |
Webhook-Variante als Sub-Pattern: SeaTable hat einen Base-Webhook auf Row-Add (https://seatable.com/help/what-are-webhooks-and-how-to-use-them/). Form-Submit ist ein Row-Add und feuert den Webhook. Externes Skript prueft, legt fehlende an, schreibt Link via JWT-API zurueck. Funktional gleich wie B, aber Logik ausserhalb SeaTable — nuetzlich wenn schon n8n/eigener Server vorhanden ist.
Default-Empfehlungs-Reihenfolge fuer Kundengespraech: A vor B vor C. Erst fragen ob die UX-Umstellung okay ist — meistens ja, dann sind null Kosten. Wenn nein, Option B als bezahlte Mini-Beauftragung (~€300-400 Range).
Konkrete Vorlage — Aktivierungs-Skript Erlei
Skript-Pfad: ../../runs/2026-04-20-erlei-seatable-scan/scripts/aktiviere_ma.py
Aufruf:
# Vorbereitung einmalig — Metadata cachen
TOKEN=$(curl -sS 'https://cloud.seatable.io/api/v2.1/dtable/app-access-token/' \
-H "Authorization: Token <BASE_TOKEN>" \
| python3 -c 'import sys,json; print(json.load(sys.stdin)["access_token"])')
curl -sS "https://cloud.seatable.io/api-gateway/api/v2/dtables/<UUID>/metadata/" \
-H "Authorization: Bearer $TOKEN" > /tmp/erlei-meta.json
# Aktivierung
SEATABLE_ACCOUNT_TOKEN=<account-token> \
python3 ../../runs/2026-04-20-erlei-seatable-scan/scripts/aktiviere_ma.py <ma-email>Output: pro geplantem Share entweder + angelegt, = bereits vorhanden, oder ! FEHLER.
Verwandte Quellen
- Erste Implementierung + Stolperer-Log: alter Pfad
~/source/agent-agentur/runs/2026-04-20-erlei-seatable-scan/03-umsetzung-2026-05-04.md(Run nicht migriert) - API-Reference offiziell: api.seatable.com/reference/introduction
- Update View Endpoint: api.seatable.com/reference/updateview
- Create User View Share: api.seatable.com/reference/createuserviewshare
- Backlog-Eintrag „SeaTable-MCP”: ideas-backlog — wann sich ein eigener MCP lohnt vs nicht.
Related
- _index — Hub aller MCP-Setups (SeaTable noch nicht eigenes MCP, aber Pattern gleich)
- anthropic-skills — wann claude-api Skill triggert