De SDK van de scripts
De acht modules van de SDK api_manager — datasources, HTTP, logs, geüploade bestanden, secrets, meldingen, workflows en rapporten — met Python-voorbeelden.
Binnen een script ligt de hele app op één import afstand. De SDK heet
api_manager en wordt module voor module geïmporteerd:
from api_manager import db, http, log, files, secrets, notify, workflow, reports
Deze acht namen zijn het volledige publieke oppervlak van de SDK — wat hier niet staat, bestaat niet tijdens de uitvoering:
| Module | Waarvoor |
|---|---|
db |
De datasources van de app bevragen (Oracle, PostgreSQL, MySQL/MariaDB, SQL Server, …). |
http |
HTTP-verzoeken aan externe diensten, met automatische JSON. |
log |
Regels naar de logs van de uitvoering schrijven. |
files |
Bestanden lezen die via een API zijn geüpload. |
secrets |
Geheimen van de app lezen, op de server ontcijferd. |
notify |
Meldingen in de app en e-mails aan de gebruikers van de app. |
workflow |
Processen starten, wachtstanden wekken en menselijke taken beslissen. |
reports |
De rapporten van de app in PDF of Excel genereren. |
De editor vult dit allemaal automatisch aan — de namen, de parameters en de documentatie van elke functie verschijnen terwijl u typt.
Dica
De knop Prompt voor LLM in de balk van de editor opent de volledige gids bij de SDK, klaar om te kopiëren met Alles kopiëren. Plak hem in Claude, ChatGPT of een andere assistent, samen met wat u het script wilt laten doen — de assistent kent dan het exacte contract en verzint geen functies die niet bestaan.

db — de datasources van de app
Naar de datasources die in de app zijn ingesteld, verwijst u met hun naam. Twee functies:
from api_manager import db
crm = db("Dados CRM")
linhas = crm.query( # lijst van dicts (kolom -> waarde)
"select id, nome from contas where cidade = ?", ["Lisboa"]
)
conta = crm.query_one( # de eerste regel, of None
"select * from contas where id = ?", [42]
)
params is een positionele lijst. De placeholders zijn die van de engine
van de datasource:
| Engine | Placeholders | Voorbeeld |
|---|---|---|
| PostgreSQL | $1, $2, … |
where id = $1 |
| MySQL / MariaDB | ? |
where id = ? |
| Oracle | :1, :2, … |
where id = :1 |
Bestaat de datasource niet, dan werpt de aanroep een fout op (en eindigt de uitvoering in Fout, als u die niet opvangt).
Atenção
Datums in Oracle: geef ze liever niet als parameter mee — het transport in
JSON maakt het type dubbelzinnig. Gebruik liever het literal in de SQL:
TO_DATE('2026-06-25','YYYY-MM-DD').
http — verzoeken aan externe diensten
Vijf werkwoorden, allemaal met automatische JSON — een body die een dict of
een lijst is, gaat als JSON mee, en een JSON-antwoord komt al gedecodeerd
binnen:
from api_manager import http, log
r = http.get("https://api.exemplo.com/clientes")
# r = {"status": int, "ok": bool, "body": <gedecodeerde json of tekst>}
if r["ok"]:
log("ontvangen", len(r["body"]), "klanten")
r = http.post(
"https://api.exemplo.com/leads",
body={"nome": "Vininha & Filhos", "origem": "keplin"},
headers={"Authorization": "Bearer abc123"},
)
Er bestaan ook http.put(url, body, headers), http.patch(url, body, headers) en http.delete(url, headers). r["ok"] is waar voor
2xx-antwoorden — een 404 of 500 werpt geen uitzondering op, controleer de
status zelf.
log — de logs van de uitvoering
from api_manager import log
log("bezig met verwerken", 42, {"fase": "inicial"})
Het accepteert meerdere argumenten, net als print — en elke aanroep is een
regel in de logs van de uitvoering, zichtbaar in het paneel Resultaat van de
uitvoering en in de geschiedenis Uitvoeringen. De klassieke print
wordt ook opgevangen, maar log is de canonieke vorm van de SDK.

files — geüploade bestanden
Wanneer een API van de app een argument van het type Upload heeft, stuurt
de client een bestand en ontvangt het script het in input["args"] als een
handle — de bytes blijven op schijf, niet in het geheugen. De module files
werkt op die handle:
from api_manager import files
def main(input):
f = input["args"]["ficheiro"] # de handle van de upload
texto = files.read_text(f) # str (utf-8)
dados = files.read(f) # bytes
caminho = files.path(f) # absoluut pad op schijf
files.save(f, "ultimo-recebido.csv") # kopieert naar de map van het script
return {"nome": f["filename"], "tamanho": f["size"]}
De handle brengt filename, mimeType en size mee — handig om te valideren
vóór het verwerken.
secrets — geheimen van de app
Tokens en sleutels bewaart u op de pagina Secrets van de app (boomstructuur in de zijbalk, groep App), versleuteld. Het script leest ze op sleutel:
from api_manager import secrets
token = secrets.get("STRIPE_KEY") # -> str | None
if token is None:
raise RuntimeError("Secret STRIPE_KEY is in deze app niet ingesteld.")
De waarde wordt op de server ontcijferd, op het moment van de uitvoering — ze verschijnt nooit in de browser en blijft nooit in de code staan.

Atenção
Doe geen log(token). De logs blijven in de geschiedenis van de
uitvoeringen staan — een geheim dat in een log is geschreven, is geen geheim
meer.
notify — meldingen en e-mails
De app heeft twee vaste kanalen — een in de app en een via e-mail —
die u kunt inschakelen in de instellingen voor Meldingen van de app (daar
leven ook de SMTP-configuratie en de afzender). users zijn gebruikersnamen
van gebruikers van de app; roles breiden uit naar alle leden van de rol.
In de app, in real time:
from api_manager import notify
r = notify.send(
"Rapport klaar",
subtitle="Maandrapporten",
body="Het maandrapport is beschikbaar.",
users=["joao"],
roles=None,
data={"url": "/relatorios/42"},
)
# r = {"recipients": int, "delivered": int}
delivered telt de meldingen die in real time zijn bezorgd, aan wie verbonden
is; de rest blijft in de inbox staan en komt binnen zodra men inlogt.
E-mail:
r = notify.email(
"Voorraadwaarschuwing",
to=["chefe@empresa.pt"], # vrije adressen
users=None,
roles=["admin"], # en/of gebruikers en rollen van de app
text="Voorraad onder het minimum.",
html=None,
)
# r = {"accepted": [emails], "skipped": [gebruikersnamen zonder e-mail]}
Het versturen via SMTP gebeurt asynchroon op de server — het script wacht er
niet op. attachments accepteert bijlagen met de inhoud in base64 (zie
reports hieronder voor het typische geval).
workflow — de processen van de app
Een script kan een proces starten, wie op een gebeurtenis wacht wekken, en
menselijke taken beslissen. Naar het proces verwijst u met zijn naam (of met
de stabiele identificatie); key is de sleutel van het record waarop het
draait:
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")
# openstaande taken van die gebruiker van de app, met de mogelijke beslissingen
r = workflow.complete(task=17, outcome="aprovar", as_user="joao",
data={"nota": "ok"})
# r = {"ok": bool}
Regels die ertoe doen:
workflow.startkeert terug zodra de motor bij de eerste wachtstand aankomt — het wacht nooit tot het proces klaar is.workflow.signalzonderkeywekt alle processen die op die gebeurtenis stilstaan;{"woken": 0}is geen fout — er kan gewoon niemand staan wachten.- In
workflow.completeisas_userverplicht (wie beslist, blijft in de geschiedenis staan) en moet de taak aan die gebruiker zijn toegewezen. De waarden vanoutcomezijn de uitgangen van de knoop van de taak — dezelfde die de persoon als knoppen ziet. Verzin geen namen.
reports — rapporten van de app genereren
Het document wordt op de server gegenereerd, met de gegevens van de app, uitgaand van een bestaand rapport:
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(
"Facturen van maart",
to=["financeiro@empresa.pt"],
text="Zie de bijlage.",
attachments=[{"filename": r["filename"], "content": r["base64"]}],
)
Het derde, optionele argument is het formaat: "pdf" (standaard) of
"xlsx". De parameters zijn die welke het rapport declareert. In het
resultaat komt bytes klaar om naar schijf te schrijven en base64 klaar om
aan een e-mail te hangen.
Een volledig voorbeeld
In de trant van het script atualizar_indicadores van de app
Klantenbeheer — het leest de pipeline, schrijft nuttige logs en
waarschuwt wanneer er afsluitingen naderen:
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"], "opportuniteiten /", abertas["total"], "EUR")
if fechos:
notify.send(
"Afsluitingen deze week",
body=f"{len(fechos)} opportuniteiten met een verwachte afsluiting tot {limite}.",
roles=["comercial"],
)
return {
"oportunidades_abertas": abertas["n"],
"valor_pipeline": abertas["total"],
"fechos_proximos_7_dias": len(fechos),
}
Grenzen en goede gewoonten
- Het resultaat van
mainmoet serialiseerbaar zijn in JSON; maximaal 32 MB. - Elke uitvoering respecteert de Tijdslimiet van het script (30 seconden tot 10 minuten) — bij overschrijding wordt het proces beëindigd en blijft het op Time-out staan.
- De uitvoeringen zijn geïsoleerd: reken niet op variabelen uit een vorige uitvoering. Bewaar dingen in bestanden in de map van het script of in een datasource.
- Doe
log(...)bij elke relevante fase — dat is wat u gaat lezen wanneer er op een zondagochtend om 7.00 uur iets misgaat. - Vang de herstelbare fouten op en leg ze vast; laat de fatale fouten opborrelen — een niet-opgevangen uitzondering markeert de uitvoering als Fout, en dat is precies wat u in de geschiedenis wilt zien wanneer er echt iets mis is.
- Druk geen geheimen af, en lees ze altijd uit
secrets— schrijf ze nooit in de code.
Veelgestelde vragen
from api_manager import db mislukt op mijn computer.
Dat is te verwachten: de module api_manager bestaat alleen tijdens de
uitvoering op het platform — daar wordt hij geïnjecteerd. In de editor hebt
u het volledige automatisch aanvullen van de SDK; het bestand
api_manager.py dat u in de map van het script ziet, bestaat alleen
daarvoor.
db("nome") zegt dat de datasource niet bestaat.
De naam moet exact die van de datasource in de app zijn (bijv.: Dados CRM, met hoofdletters en spatie). Zie de lijst in de sectie Datasources
van de boom.
De notify.email gaf accepted terug, maar de e-mail is niet aangekomen.
Het versturen via SMTP is asynchroon — accepted betekent dat de e-mail naar
het e-mailkanaal van de app is doorgestuurd. Controleer de SMTP-configuratie
in de instellingen voor Meldingen van de app en de spammap van de
ontvanger.
Kan ik de SDK in de validatie van een venster gebruiken?
Ja — de validatie draait in dezelfde omgeving als het hoofdscript, met
dezelfde input en dezelfde SDK. Zie Planningen.