Das SDK der Skripte
Die acht Module des SDK api_manager — Datenquellen, HTTP, Logs, hochgeladene Dateien, Secrets, Benachrichtigungen, Workflows und Berichte — mit Python-Beispielen.
Innerhalb eines Skripts ist die ganze App nur einen import entfernt. Das SDK
heißt api_manager und wird Modul für Modul importiert:
from api_manager import db, http, log, files, secrets, notify, workflow, reports
Diese acht Namen sind die gesamte öffentliche Oberfläche des SDK — was hier nicht steht, existiert zur Laufzeit nicht:
| Modul | Wofür |
|---|---|
db |
Die Datenquellen der App abfragen (Oracle, PostgreSQL, MySQL/MariaDB, SQL Server, …). |
http |
HTTP-Anfragen an externe Dienste, mit automatischem JSON. |
log |
Zeilen in die Logs der Ausführung schreiben. |
files |
Über eine API hochgeladene Dateien lesen. |
secrets |
Geheimnisse der App lesen, auf dem Server entschlüsselt. |
notify |
In-App-Benachrichtigungen und E-Mails an die Benutzer der App. |
workflow |
Prozesse starten, Wartezustände aufwecken und menschliche Aufgaben entscheiden. |
reports |
Die Berichte der App als PDF oder Excel erzeugen. |
Der Editor vervollständigt all das automatisch — die Namen, die Parameter und die Dokumentation jeder Funktion erscheinen, während Sie schreiben.
Dica
Die Schaltfläche Prompt für LLM in der Leiste des Editors öffnet den vollständigen Leitfaden zum SDK, fertig zum Kopieren mit Alles kopieren. Fügen Sie ihn in Claude, ChatGPT oder einen anderen Assistenten ein, zusammen mit dem, was das Skript tun soll — der Assistent kennt dann den genauen Vertrag und erfindet keine Funktionen, die es nicht gibt.

db — die Datenquellen der App
Die in der App konfigurierten Datenquellen werden über ihren Namen referenziert. Zwei Funktionen:
from api_manager import db
crm = db("Dados CRM")
linhas = crm.query( # Liste von Dicts (Spalte -> Wert)
"select id, nome from contas where cidade = ?", ["Lisboa"]
)
conta = crm.query_one( # die erste Zeile, oder None
"select * from contas where id = ?", [42]
)
params ist eine positionelle Liste. Die Platzhalter sind die der
Engine der Datenquelle:
| Engine | Platzhalter | Beispiel |
|---|---|---|
| PostgreSQL | $1, $2, … |
where id = $1 |
| MySQL / MariaDB | ? |
where id = ? |
| Oracle | :1, :2, … |
where id = :1 |
Existiert die Datenquelle nicht, wirft der Aufruf einen Fehler (und die Ausführung endet mit Fehler, wenn Sie ihn nicht abfangen).
Atenção
Datumsangaben in Oracle: Übergeben Sie sie besser nicht als Parameter — der
Transport per JSON macht den Typ mehrdeutig. Bevorzugen Sie das Literal im
SQL: TO_DATE('2026-06-25','YYYY-MM-DD').
http — Anfragen an externe Dienste
Fünf Verben, alle mit automatischem JSON — ein body als Dict oder Liste geht
als JSON hinaus, und eine JSON-Antwort kommt bereits dekodiert an:
from api_manager import http, log
r = http.get("https://api.exemplo.com/clientes")
# r = {"status": int, "ok": bool, "body": <dekodiertes JSON oder Text>}
if r["ok"]:
log("empfangen", len(r["body"]), "Kunden")
r = http.post(
"https://api.exemplo.com/leads",
body={"nome": "Vininha & Filhos", "origem": "keplin"},
headers={"Authorization": "Bearer abc123"},
)
Es gibt auch http.put(url, body, headers), http.patch(url, body, headers) und http.delete(url, headers). r["ok"] ist wahr für
2xx-Antworten — ein 404 oder 500 wirft keine Ausnahme, prüfen Sie den
Status selbst.
log — die Logs der Ausführung
from api_manager import log
log("wird verarbeitet", 42, {"fase": "inicial"})
Es nimmt mehrere Argumente entgegen, wie print — und jeder Aufruf ist eine
Zeile in den Logs der Ausführung, sichtbar im Panel Ergebnis der
Ausführung und in der Historie Ausführungen. Das klassische print wird
ebenfalls erfasst, aber log ist die kanonische Form des SDK.

files — hochgeladene Dateien
Wenn eine API der App ein Argument vom Typ Upload hat, schickt der Client
eine Datei und das Skript erhält sie in input["args"] als Handle — die
Bytes liegen auf der Festplatte, nicht im Speicher. Das Modul files
arbeitet auf diesem Handle:
from api_manager import files
def main(input):
f = input["args"]["ficheiro"] # das Handle des Uploads
texto = files.read_text(f) # str (utf-8)
dados = files.read(f) # bytes
caminho = files.path(f) # absoluter Pfad auf der Festplatte
files.save(f, "ultimo-recebido.csv") # kopiert in den Ordner des Skripts
return {"nome": f["filename"], "tamanho": f["size"]}
Das Handle bringt filename, mimeType und size mit — nützlich, um vor der
Verarbeitung zu prüfen.
secrets — Geheimnisse der App
Tokens und Schlüssel liegen verschlüsselt auf der Seite Secrets der App (seitlicher Baum, Gruppe App). Das Skript liest sie über den Schlüssel:
from api_manager import secrets
token = secrets.get("STRIPE_KEY") # -> str | None
if token is None:
raise RuntimeError("Secret STRIPE_KEY in dieser App nicht konfiguriert.")
Der Wert wird auf dem Server entschlüsselt, im Moment der Ausführung — er erscheint nie im Browser und bleibt nicht im Code.

Atenção
Machen Sie kein log(token). Die Logs bleiben in der Ausführungshistorie —
ein Geheimnis, das in ein Log geschrieben wurde, ist kein Geheimnis mehr.
notify — Benachrichtigungen und E-Mails
Die App hat zwei feste Kanäle — einen In-App-Kanal und einen für
E-Mail —, aktivierbar in den Einstellungen für Benachrichtigungen der
App (dort wohnen die SMTP-Konfiguration und der Absender). users sind
Benutzernamen von Benutzern der App; roles weiten sich auf alle
Mitglieder der Rolle aus.
In-App, in Echtzeit:
from api_manager import notify
r = notify.send(
"Bericht fertig",
subtitle="Monatsberichte",
body="Der Monatsbericht ist verfügbar.",
users=["joao"],
roles=None,
data={"url": "/relatorios/42"},
)
# r = {"recipients": int, "delivered": int}
delivered zählt die in Echtzeit Zugestellten, an alle, die verbunden sind;
die übrigen bleiben im Posteingang und erhalten sie beim Anmelden.
E-Mail:
r = notify.email(
"Bestandswarnung",
to=["chefe@empresa.pt"], # freie Adressen
users=None,
roles=["admin"], # und/oder Benutzer und Rollen der App
text="Bestand unter dem Minimum.",
html=None,
)
# r = {"accepted": [emails], "skipped": [usernames ohne E-Mail]}
Der SMTP-Versand geschieht asynchron auf dem Server — das Skript wartet nicht.
attachments nimmt Anhänge mit dem Inhalt in base64 entgegen (siehe reports
weiter unten für den typischen Fall).
workflow — die Prozesse der App
Ein Skript kann einen Prozess starten, jene aufwecken, die auf ein Ereignis
warten, und menschliche Aufgaben entscheiden. Der Prozess wird über seinen
Namen referenziert (oder über seine stabile Kennung); key ist der Schlüssel
des Datensatzes, auf dem er läuft:
from api_manager import workflow
r = workflow.start("Aprovação de despesa", 42, data={"valor": 1200})
# r = {"instanceId": int}
r = workflow.signal("visto", key=42)
# r = {"woken": int}
abertas = workflow.tasks("joao")
# offene Aufgaben dieses Benutzers der App, mit den möglichen Entscheidungen
r = workflow.complete(task=17, outcome="aprovar", as_user="joao",
data={"nota": "ok"})
# r = {"ok": bool}
Regeln, die zählen:
workflow.startgibt zurück, sobald die Maschine die erste Wartestelle erreicht — es wartet nie darauf, dass der Prozess endet.workflow.signalohnekeyweckt alle Prozesse auf, die bei diesem Ereignis stehen;{"woken": 0}ist kein Fehler — es kann sein, dass niemand wartet.- Bei
workflow.completeistas_userverpflichtend (wer entscheidet, bleibt in der Historie) und die Aufgabe muss diesem Benutzer zugewiesen sein. Die Werte vonoutcomesind die Ausgänge des Aufgabenknotens — dieselben, die die Person als Schaltflächen sieht. Erfinden Sie keine Namen.
reports — Berichte der App erzeugen
Das Dokument wird auf dem Server erzeugt, mit den Daten der App, ausgehend von einem bestehenden Bericht:
from api_manager import notify, reports
r = reports.render("Facturas do mês", {"mes": "2026-03"})
# r = {"filename", "pages", "format", "mime", "bytes", "base64"}
notify.email(
"Rechnungen für März",
to=["financeiro@empresa.pt"],
text="Anbei das Dokument.",
attachments=[{"filename": r["filename"], "content": r["base64"]}],
)
Das dritte, optionale Argument ist das Format: "pdf" (Standard) oder
"xlsx". Die Parameter sind die, die der Bericht deklariert. Im Ergebnis
kommt bytes fertig zum Schreiben auf die Festplatte und base64 fertig zum
Anhängen an eine E-Mail.
Ein vollständiges Beispiel
In der Art des Skripts atualizar_indicadores der App Kundenverwaltung —
es liest die Pipeline, schreibt nützliche Logs und meldet sich, wenn
Abschlüsse bevorstehen:
from datetime import date, timedelta
from api_manager import db, log, notify
def main(input):
crm = db("Dados CRM")
abertas = crm.query_one(
"select count(*) as n, coalesce(sum(valor), 0) as total "
"from oportunidades where fase not in ('fechada_ganha', 'fechada_perdida')"
)
limite = (date.today() + timedelta(days=7)).isoformat()
fechos = crm.query(
"select titulo, data_fecho from oportunidades "
"where fase not in ('fechada_ganha', 'fechada_perdida') "
"and data_fecho <= ? order by data_fecho",
[limite],
)
log("Pipeline:", abertas["n"], "Verkaufschancen /", abertas["total"], "EUR")
if fechos:
notify.send(
"Abschlüsse in dieser Woche",
body=f"{len(fechos)} Verkaufschancen mit geplantem Abschluss bis {limite}.",
roles=["comercial"],
)
return {
"oportunidades_abertas": abertas["n"],
"valor_pipeline": abertas["total"],
"fechos_proximos_7_dias": len(fechos),
}
Grenzen und gute Praxis
- Das Ergebnis von
mainmuss JSON-serialisierbar sein; maximal 32 MB. - Jede Ausführung achtet auf das Zeitlimit des Skripts (30 Sekunden bis 10 Minuten) — bei Überschreitung wird der Prozess beendet und bleibt auf Timeout.
- Die Ausführungen sind isoliert: Verlassen Sie sich nicht auf Variablen einer vorherigen Ausführung. Speichern Sie dauerhaft in Dateien des Skript-Ordners oder in einer Datenquelle.
- Setzen Sie in jeder relevanten Phase ein
log(...)— das ist es, was Sie lesen werden, wenn etwas an einem Sonntag um 7:00 Uhr fehlschlägt. - Fangen Sie die behebbaren Fehler ab und protokollieren Sie sie; lassen Sie die fatalen durch — eine nicht abgefangene Ausnahme markiert die Ausführung als Fehler, und genau das wollen Sie in der Historie sehen, wenn wirklich etwas im Argen liegt.
- Geben Sie keine Geheimnisse aus und lesen Sie sie immer über
secrets— schreiben Sie sie nie in den Code.
Häufige Fragen
from api_manager import db schlägt auf meinem Rechner fehl.
Das ist zu erwarten: Das Modul api_manager existiert nur bei der
Ausführung auf der Plattform — dort wird es eingespeist. Im Editor haben Sie
die vollständige Autovervollständigung des SDK; die Datei api_manager.py,
die Sie im Ordner des Skripts sehen, existiert nur dafür.
db("nome") sagt, dass die Datenquelle nicht existiert.
Der Name muss exakt dem der Datenquelle in der App entsprechen (z. B.:
Dados CRM, mit Großbuchstaben und Leerzeichen). Die Liste sehen Sie im
Abschnitt Datenquellen des Baums.
notify.email hat accepted zurückgegeben, aber die E-Mail kam nicht an.
Der SMTP-Versand ist asynchron — accepted bedeutet, dass die E-Mail an den
E-Mail-Kanal der App weitergereicht wurde. Prüfen Sie die SMTP-Konfiguration in
den Einstellungen für Benachrichtigungen der App und den Spam-Ordner des
Empfängers.
Kann ich das SDK in der Validierung eines Fensters verwenden?
Ja — die Validierung läuft in derselben Umgebung wie das Hauptskript, mit
demselben input und demselben SDK. Siehe
Zeitpläne.