KEPLIN Docs

Skriptens SDK

SDK:n api_managers åtta moduler — datakällor, HTTP, loggar, uppladdade filer, secrets, aviseringar, arbetsflöden och rapporter — med Python-exempel.

Inne i ett skript ligger hela appen inom räckhåll för ett import. SDK:n heter api_manager och importeras modul för modul:

from api_manager import db, http, log, files, secrets, notify, workflow, reports

De här åtta namnen är hela SDK:ns publika yta — det som inte står här finns inte vid körning:

Modul Till vad
db Fråga appens datakällor (Oracle, PostgreSQL, MySQL/MariaDB, SQL Server, …).
http HTTP-anrop till externa tjänster, med automatisk JSON.
log Skriva rader i körningens loggar.
files Läsa filer som skickats via uppladdning i ett API.
secrets Läsa appens hemligheter, dekrypterade på servern.
notify Aviseringar i appen och e-post till appens användare.
workflow Starta arbetsflöden, väcka väntande steg och avgöra mänskliga uppgifter.
reports Skapa appens rapporter som PDF eller Excel.

Editorn autokompletterar allt detta — namnen, parametrarna och dokumentationen för varje funktion dyker upp medan du skriver.

Dica

Knappen Prompt för LLM i editorns rad öppnar hela SDK-guiden, redo att kopiera med Kopiera allt. Klistra in den i Claude, ChatGPT eller någon annan assistent, tillsammans med vad du vill att skriptet ska göra — assistenten känner då till det exakta kontraktet och hittar inte på funktioner som inte finns.

Prompt för LLM — hela SDK-kontraktet i en text redo att klistras in i en AI-assistent.
Prompt för LLM — hela SDK-kontraktet i en text redo att klistras in i en AI-assistent.

db — appens datakällor

Datakällorna som konfigurerats i appen refereras med namn. Två funktioner:

from api_manager import db

crm = db("Dados CRM")

linhas = crm.query(          # lista med dictar (kolumn -> värde)
    "select id, nome from contas where cidade = ?", ["Lisboa"]
)
conta = crm.query_one(       # första raden, eller None
    "select * from contas where id = ?", [42]
)

params är en positionell lista. Platshållarna är motorns egna i datakällan:

Motor Platshållare Exempel
PostgreSQL $1, $2, … where id = $1
MySQL / MariaDB ? where id = ?
Oracle :1, :2, … where id = :1

Om datakällan inte finns kastar anropet ett fel (och körningen slutar med Fel, om du inte fångar det).

Atenção

Datum i Oracle: undvik att skicka dem som parameter — transporten i JSON gör typen tvetydig. Föredra en literal i SQL:en: TO_DATE('2026-06-25','YYYY-MM-DD').

http — anrop till externa tjänster

Fem verb, alla med automatisk JSON — en body som är dict eller lista skickas som JSON, och ett JSON-svar kommer redan avkodat:

from api_manager import http, log

r = http.get("https://api.exemplo.com/clientes")
# r = {"status": int, "ok": bool, "body": <avkodad json eller text>}
if r["ok"]:
    log("mottog", len(r["body"]), "kunder")

r = http.post(
    "https://api.exemplo.com/leads",
    body={"nome": "Vininha & Filhos", "origem": "keplin"},
    headers={"Authorization": "Bearer abc123"},
)

Det finns också http.put(url, body, headers), http.patch(url, body, headers) och http.delete(url, headers). r["ok"] är sant för 2xx-svar — en 404 eller 500 kastar inget undantag, kontrollera statusen själv.

log — körningens loggar

from api_manager import log

log("bearbetar", 42, {"fase": "inicial"})

Den tar emot flera argument, som print — och varje anrop blir en rad i körningens loggar, synlig i panelen Körningens resultat och i historiken Körningar. Klassisk print fångas också upp, men log är SDK:ns kanoniska form.

Detaljen för en körning — det returnerade resultatet och loggraderna som skriptet skrev.
Detaljen för en körning — det returnerade resultatet och loggraderna som skriptet skrev.

files — uppladdade filer

När ett API i appen har ett argument av typen Upload skickar klienten en fil och skriptet tar emot den i input["args"] som ett handle — byten ligger på disk, inte i minnet. Modulen files arbetar mot det handtaget:

from api_manager import files


def main(input):
    f = input["args"]["ficheiro"]      # uppladdningens handtag
    texto = files.read_text(f)         # str (utf-8)
    dados = files.read(f)              # bytes
    caminho = files.path(f)            # absolut sökväg på disk
    files.save(f, "ultimo-recebido.csv")   # kopierar till skriptets mapp
    return {"nome": f["filename"], "tamanho": f["size"]}

Handtaget innehåller filename, mimeType och size — bra för att validera innan du bearbetar.

secrets — appens hemligheter

Tokens och nycklar sparas på appens sida Secrets (trädet i sidopanelen, gruppen App), krypterade. Skriptet läser dem med nyckeln:

from api_manager import secrets

token = secrets.get("STRIPE_KEY")   # -> str | None
if token is None:
    raise RuntimeError("Hemligheten STRIPE_KEY är inte konfigurerad i den här appen.")

Värdet dekrypteras på servern, i körningsögonblicket — det syns aldrig i webbläsaren och hamnar aldrig i koden.

Appens sida Secrets — nycklarna som skripten läser med secrets.get.
Appens sida Secrets — nycklarna som skripten läser med secrets.get.

Atenção

Gör inte log(token). Loggarna ligger kvar i körningshistoriken — en hemlighet som skrivits i en logg är inte längre en hemlighet.

notify — aviseringar och e-post

Appen har två fasta kanaler — en i appen och en för e-post — som aktiveras i appens inställningar för Aviseringar (det är där SMTP-konfigurationen och avsändaren bor). users är användarnamn för användare i appen; roles expanderar till alla medlemmar i rollen.

I appen, i realtid:

from api_manager import notify

r = notify.send(
    "Rapporten är klar",
    subtitle="Månadsrapporter",
    body="Månadsrapporten finns tillgänglig.",
    users=["joao"],
    roles=None,
    data={"url": "/relatorios/42"},
)
# r = {"recipients": int, "delivered": int}

delivered räknar dem som levererats i realtid, till dem som är uppkopplade; de övriga ligger kvar i inkorgen och tar emot dem när de loggar in.

E-post:

r = notify.email(
    "Lagervarning",
    to=["chefe@empresa.pt"],      # fria adresser
    users=None,
    roles=["admin"],              # och/eller appens användare och roller
    text="Lagret är under miniminivån.",
    html=None,
)
# r = {"accepted": [e-postadresser], "skipped": [användarnamn utan e-post]}

SMTP-utskicket sker asynkront på servern — skriptet väntar inte. attachments tar emot bilagor med innehållet i base64 (se reports nedan för det typiska fallet).

workflow — appens arbetsflöden

Ett skript kan starta ett arbetsflöde, väcka den som väntar på en händelse, och avgöra mänskliga uppgifter. Arbetsflödet refereras med namn (eller med den stabila identifieraren); key är nyckeln till posten som det körs 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")
# öppna uppgifter för den appanvändaren, med de möjliga besluten

r = workflow.complete(task=17, outcome="aprovar", as_user="joao",
                      data={"nota": "ok"})
# r = {"ok": bool}

Regler som spelar roll:

  • workflow.start återvänder så snart motorn når den första väntan — den väntar aldrig på att arbetsflödet ska bli klart.
  • workflow.signal utan key väcker alla arbetsflöden som stannat på den händelsen; {"woken": 0} är inget fel — det kanske inte finns någon som väntar.
  • I workflow.complete är as_user obligatoriskt (den som beslutar hamnar i historiken) och uppgiften måste vara tilldelad den användaren. Värdena för outcome är uppgiftsnodens utgångar — samma som personen ser som knappar. Hitta inte på namn.

reports — skapa appens rapporter

Dokumentet skapas på servern, med appens data, utifrån en befintlig 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(
    "Fakturor för mars",
    to=["financeiro@empresa.pt"],
    text="Bifogat följer dokumentet.",
    attachments=[{"filename": r["filename"], "content": r["base64"]}],
)

Det tredje, valfria argumentet är formatet: "pdf" (standard) eller "xlsx". Parametrarna är de som rapporten deklarerar. I resultatet kommer bytes redo att skrivas till disk och base64 redo att bifogas i ett e-postmeddelande.

Ett komplett exempel

I stil med skriptet atualizar_indicadores i appen Kundhantering — det läser pipelinen, skriver användbara loggar och varnar när avslut närmar sig:

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"], "affärsmöjligheter /", abertas["total"], "EUR")
    if fechos:
        notify.send(
            "Avslut den här veckan",
            body=f"{len(fechos)} affärsmöjligheter med planerat avslut till {limite}.",
            roles=["comercial"],
        )

    return {
        "oportunidades_abertas": abertas["n"],
        "valor_pipeline": abertas["total"],
        "fechos_proximos_7_dias": len(fechos),
    }

Gränser och god praxis

  • Resultatet från main måste vara serialiserbart som JSON; max 32 MB.
  • Varje körning respekterar skriptets Tidsgräns (30 sekunder till 10 minuter) — överskrids den avslutas processen och körningen blir Timeout.
  • Körningarna är isolerade: förlita dig inte på variabler från en tidigare körning. Spara varaktigt i filer i skriptets mapp eller i en datakälla.
  • Gör log(...) i varje relevant fas — det är det du kommer att läsa när något går fel kl. 07.00 en söndag.
  • Fånga de fel som går att hantera och registrera dem; låt de fatala stiga — ett ofångat undantag markerar körningen som Fel, och det är det du vill se i historiken när något verkligen är galet.
  • Skriv aldrig ut hemligheter, och läs dem alltid från secrets — lägg dem aldrig i koden.

Vanliga frågor

from api_manager import db misslyckas på min dator. Det är väntat: modulen api_manager finns bara vid körning på plattformen — det är där den injiceras. I editorn har du full autokomplettering för SDK:n; filen api_manager.py som du ser i skriptets mapp finns bara för det ändamålet.

db("nome") säger att datakällan inte finns. Namnet måste vara exakt datakällans namn i appen (t.ex.: Dados CRM, med versaler och mellanslag). Se listan i avsnittet Datakällor i trädet.

notify.email returnerade accepted men e-posten kom aldrig fram. SMTP-utskicket är asynkront — accepted betyder att e-posten gick vidare till appens e-postkanal. Kontrollera SMTP-konfigurationen i appens inställningar för Aviseringar och mottagarens skräppost.

Kan jag använda SDK:n i ett fönsters validering? Ja — valideringen körs i samma miljö som huvudskriptet, med samma input och samma SDK. Se Scheman.