KEPLIN Docs

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.

Prompt til LLM — hele kontrakten til SDK-en i en tekst som er klar til å limes inn i en KI-assistent.
Prompt til LLM — hele kontrakten til SDK-en i en tekst som er klar til å limes inn i en KI-assistent.

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.

Detaljen for en kjøring — resultatet som ble returnert, og logglinjene skriptet skrev.
Detaljen for en kjøring — resultatet som ble returnert, og logglinjene skriptet skrev.

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.

Siden Hemmeligheter i appen — nøklene som skriptene leser med secrets.get.
Siden Hemmeligheter i appen — nøklene som skriptene leser med secrets.get.

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.start returnerer straks motoren når det første ventepunktet — den venter aldri på at prosessen skal bli ferdig.
  • workflow.signal uten key vekker alle prosessene som står stille på den hendelsen; {"woken": 0} er ikke en feil — det kan hende ingen venter.
  • I workflow.complete er as_user påkrevd (den som avgjør blir stående i historikken), og oppgaven må være tildelt den brukeren. Verdiene til outcome er 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 main må 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.