SDK-en for skript
De åtte modulene i SDK-en api_manager — datakilder, HTTP, logger, opplastede filer, hemmeligheter, varsler, arbeidsflyter og rapporter — med Python-eksempler.
Inne i et skript er hele appen innen rekkevidde av én import. SDK-en heter
api_manager og importeres modul for modul:
from api_manager import db, http, log, files, secrets, notify, workflow, reports
Disse åtte navnene er hele den offentlige overflaten til SDK-en — det som ikke står her, finnes ikke under kjøring:
| Modul | Til hva |
|---|---|
db |
Spørre datakildene i appen (Oracle, PostgreSQL, MySQL/MariaDB, SQL Server, …). |
http |
HTTP-forespørsler til eksterne tjenester, med automatisk JSON. |
log |
Skrive linjer i loggene for kjøringen. |
files |
Lese filer som er lastet opp gjennom et API. |
secrets |
Lese hemmeligheter i appen, dekryptert på serveren. |
notify |
Varsler i appen og e-post til brukerne av appen. |
workflow |
Starte prosesser, vekke ventende steg og avgjøre menneskelige oppgaver. |
reports |
Lage rapportene i appen som PDF eller Excel. |
Editoren fullfører alt dette automatisk — navnene, parameterne og dokumentasjonen til hver funksjon dukker opp mens du skriver.
Dica
Knappen Prompt til LLM på linjen i editoren åpner hele guiden til SDK-en, klar til å kopieres med Kopier alt. Lim den inn i Claude, ChatGPT eller en annen assistent, sammen med det du vil at skriptet skal gjøre — assistenten kjenner da den nøyaktige kontrakten og finner ikke opp funksjoner som ikke finnes.

db — datakildene i appen
Datakildene som er satt opp i appen refereres til med navnet. To funksjoner:
from api_manager import db
crm = db("Dados CRM")
linhas = crm.query( # liste med dicts (kolonne -> verdi)
"select id, nome from contas where cidade = ?", ["Lisboa"]
)
conta = crm.query_one( # den første raden, eller None
"select * from contas where id = ?", [42]
)
params er en posisjonell liste. Plassholderne er motorens egne i
datakilden:
| Motor | Plassholdere | Eksempel |
|---|---|---|
| PostgreSQL | $1, $2, … |
where id = $1 |
| MySQL / MariaDB | ? |
where id = ? |
| Oracle | :1, :2, … |
where id = :1 |
Finnes ikke datakilden, kaster kallet en feil (og kjøringen ender med Feil, hvis du ikke fanger den opp).
Atenção
Datoer i Oracle: unngå å sende dem som parameter — transporten i JSON gjør
typen tvetydig. Bruk heller literalen i SQL-en:
TO_DATE('2026-06-25','YYYY-MM-DD').
http — forespørsler til eksterne tjenester
Fem verb, alle med automatisk JSON — en body som er dict eller liste sendes
som JSON, og et JSON-svar kommer ferdig dekodet:
from api_manager import http, log
r = http.get("https://api.exemplo.com/clientes")
# r = {"status": int, "ok": bool, "body": <dekodet json eller tekst>}
if r["ok"]:
log("mottok", len(r["body"]), "kunder")
r = http.post(
"https://api.exemplo.com/leads",
body={"nome": "Vininha & Filhos", "origem": "keplin"},
headers={"Authorization": "Bearer abc123"},
)
Det finnes også http.put(url, body, headers), http.patch(url, body, headers) og http.delete(url, headers). r["ok"] er sann for 2xx-svar — en
404 eller 500 kaster ikke unntak, du må selv sjekke statusen.
log — loggene for kjøringen
from api_manager import log
log("behandler", 42, {"fase": "inicial"})
Den tar imot flere argumenter, som print — og hvert kall er en linje i
loggene for kjøringen, synlig i panelet Resultatet av kjøringen og i
historikken Kjøringer. Den klassiske print fanges også opp, men log
er den kanoniske formen i SDK-en.

files — filer som er lastet opp
Når et API i appen har et argument av typen Upload, sender klienten en
fil, og skriptet får den i input["args"] som et handle — bytene ligger på
disk, ikke i minnet. Modulen files opererer på det handlet:
from api_manager import files
def main(input):
f = input["args"]["ficheiro"] # handlet til opplastingen
texto = files.read_text(f) # str (utf-8)
dados = files.read(f) # bytes
caminho = files.path(f) # absolutt sti på disk
files.save(f, "ultimo-recebido.csv") # kopierer til mappen til skriptet
return {"nome": f["filename"], "tamanho": f["size"]}
Handlet bringer med seg filename, mimeType og size — nyttig for å
validere før du behandler.
secrets — hemmeligheter i appen
Tokener og nøkler lagres på siden Hemmeligheter i appen (sidetreet, gruppen App), krypterte. Skriptet leser dem med nøkkelen:
from api_manager import secrets
token = secrets.get("STRIPE_KEY") # -> str | None
if token is None:
raise RuntimeError("Hemmeligheten STRIPE_KEY er ikke satt opp i denne appen.")
Verdien dekrypteres på serveren, i det øyeblikket kjøringen skjer — den dukker aldri opp i nettleseren og blir aldri liggende i koden.

Atenção
Ikke gjør log(token). Loggene blir liggende i historikken over kjøringer
— en hemmelighet skrevet i en logg er ikke lenger en hemmelighet.
notify — varsler og e-post
Appen har to faste kanaler — en i appen og en for e-post — som slås
på i innstillingene for Varsler i appen (det er der SMTP-oppsettet og
avsenderen bor). users er brukernavn til brukere av appen; roles
utvides til alle medlemmene i rollen.
I appen, i sanntid:
from api_manager import notify
r = notify.send(
"Rapporten er klar",
subtitle="Månedsrapporter",
body="Månedsrapporten er tilgjengelig.",
users=["joao"],
roles=None,
data={"url": "/relatorios/42"},
)
# r = {"recipients": int, "delivered": int}
delivered teller dem som ble levert i sanntid, til dem som er tilkoblet; de
øvrige blir liggende i innboksen og mottar når de logger inn.
E-post:
r = notify.email(
"Lagervarsel",
to=["chefe@empresa.pt"], # frie adresser
users=None,
roles=["admin"], # og/eller brukere og roller i appen
text="Lageret er under minimum.",
html=None,
)
# r = {"accepted": [e-postadresser], "skipped": [brukernavn uten e-post]}
SMTP-sendingen skjer asynkront på serveren — skriptet venter ikke.
attachments tar imot vedlegg med innholdet i base64 (se reports nedenfor
for det typiske tilfellet).
workflow — prosessene i appen
Et skript kan starte en prosess, vekke dem som venter på en hendelse, og
avgjøre menneskelige oppgaver. Prosessen refereres til med navnet (eller med
den stabile identifikatoren); key er nøkkelen til posten den kjører på:
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")
# åpne oppgaver for den appbrukeren, med de mulige beslutningene
r = workflow.complete(task=17, outcome="aprovar", as_user="joao",
data={"nota": "ok"})
# r = {"ok": bool}
Regler som betyr noe:
workflow.startreturnerer straks motoren når det første ventepunktet — den venter aldri på at prosessen skal bli ferdig.workflow.signalutenkeyvekker alle prosessene som står stille på den hendelsen;{"woken": 0}er ikke en feil — det kan hende ingen venter.- I
workflow.completeeras_userpåkrevd (den som avgjør blir stående i historikken), og oppgaven må være tildelt den brukeren. Verdiene tiloutcomeer utgangene fra oppgavenoden — de samme som personen ser som knapper. Ikke finn opp navn.
reports — lage rapporter fra appen
Dokumentet lages på serveren, med dataene i appen, ut fra en rapport som allerede finnes:
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(
"Fakturaer for mars",
to=["financeiro@empresa.pt"],
text="Se vedlegget.",
attachments=[{"filename": r["filename"], "content": r["base64"]}],
)
Det tredje, valgfrie argumentet er formatet: "pdf" (standard) eller
"xlsx". Parameterne er de rapporten deklarerer. I resultatet kommer bytes
klart til å skrives til disk og base64 klart til å legges ved en e-post.
Et fullstendig eksempel
Av samme slag som skriptet atualizar_indicadores i appen
Kundeadministrasjon — det leser pipelinen, skriver nyttige logger og sier
fra når det nærmer seg avslutninger:
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"], "muligheter /", abertas["total"], "EUR")
if fechos:
notify.send(
"Avslutninger denne uken",
body=f"{len(fechos)} muligheter med forventet avslutning innen {limite}.",
roles=["comercial"],
)
return {
"oportunidades_abertas": abertas["n"],
"valor_pipeline": abertas["total"],
"fechos_proximos_7_dias": len(fechos),
}
Grenser og god praksis
- Resultatet av
mainmå være serialiserbart som JSON; maksimalt 32 MB. - Hver kjøring respekterer Tidsgrensen til skriptet (30 sekunder til 10 minutter) — overskrides den, avsluttes prosessen og den blir stående som Tidsavbrudd.
- Kjøringene er isolerte: ikke stol på variabler fra en tidligere kjøring. Ta vare på ting i filer i mappen til skriptet eller i en datakilde.
- Gjør
log(...)i hver fase som betyr noe — det er det du kommer til å lese når noe feiler kl. 07.00 en søndag. - Fang opp feilene du kan komme deg videre fra og registrer dem; la de fatale boble opp — et unntak som ikke fanges opp merker kjøringen som Feil, og det er det du vil se i historikken når noe virkelig er galt.
- Ikke skriv ut hemmeligheter, og les dem alltid fra
secrets— skriv dem aldri i koden.
Vanlige spørsmål
from api_manager import db feiler på datamaskinen min.
Det er som forventet: modulen api_manager finnes bare under kjøring på
plattformen — det er der den blir injisert. I editoren har du full
autofullføring av SDK-en; filen api_manager.py som du ser i mappen til
skriptet, finnes bare til det formålet.
db("navn") sier at datakilden ikke finnes.
Navnet må være nøyaktig det datakilden heter i appen (f.eks.: Dados CRM, med store bokstaver og mellomrom). Se listen i seksjonen Datakilder
i treet.
notify.email returnerte accepted, men e-posten kom aldri fram.
SMTP-sendingen er asynkron — accepted betyr at e-posten gikk videre til
e-postkanalen i appen. Sjekk SMTP-oppsettet i innstillingene for Varsler
i appen, og søppelpostmappen til mottakeren.
Kan jeg bruke SDK-en i valideringen til et vindu?
Ja — valideringen kjører i samme miljø som hovedskriptet, med den samme
input og den samme SDK-en. Se Tidsplaner.