Skip to main content

Write a function

Write the Python that an app-mode function runs, save it as a new version, and move between the versions you have saved.

Prerequisites​

  • An app-mode function to edit. To create one, follow Create, run, and delete a function.
  • An organization owner or admin account, or another cloud user with access to the site.
  • An API key or JWT for that account.

Write the entry point​

Define a function called main that takes exactly three parameters:

main.py
def main(params, user_data, sdk_client):
return {"ok": True}
ParameterCarries
paramsThe caller's input, plus keys the platform adds
user_dataThe authenticated caller
sdk_clientA TaruviBase SDK client, already authenticated as that caller

Return a JSON-serializable value. It becomes the data field of a synchronous response, and the stored result of an asynchronous one.

Two constraints decide whether code is accepted:

  • The literal text def main(params, user_data, sdk_client): must appear, so annotations, renamed parameters, and different spacing are rejected.
  • Imports must come from the permitted list. Anything else raises ImportError.

See the function signature and sandbox imports for both in full.

Reach the rest of the platform​

Use sdk_client to call TaruviBase from inside the function:

main.py
def main(params, user_data, sdk_client):
invoice = sdk_client.database.get("invoices", params["invoice_id"])
return {"status": invoice["status"]}

The client acts with the caller's permissions, so a function cannot read anything its caller could not read directly.

Handle failures explicitly​

An uncaught exception fails the execution and returns a 400 carrying the exception type and message. That is often the right outcome. Where a caller needs to distinguish failure modes, return them instead:

main.py
def main(params, user_data, sdk_client):
invoice_id = params.get("invoice_id")
if not invoice_id:
return {"ok": False, "error": "invoice_id is required"}

try:
invoice = sdk_client.database.get("invoices", invoice_id)
except Exception as exc:
log("Lookup failed", level="error", data={"error": str(exc)})
return {"ok": False, "error": "invoice not found"}

return {"ok": True, "status": invoice["status"]}

Validate params before use. On a public function it is untrusted input from anyone on the internet.

The log helper above writes a structured entry onto the run's record. See Read logs and invocations.

Save a change​

Saving code creates a new version whenever the code actually changes.

PATCH/api/apps/$TARUVI_APP_SLUG/functions/$FUNCTION_SLUG/
curl -X PATCH "$TARUVI_SITE_URL/api/apps/$TARUVI_APP_SLUG/functions/$FUNCTION_SLUG/" \
-H "Authorization: Api-Key $TARUVI_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{
"code": "def main(params, user_data, sdk_client):\n invoice_id = params.get(\"invoice_id\")\n if not invoice_id:\n return {\"ok\": False, \"error\": \"invoice_id is required\"}\n log(\"Syncing invoice\", level=\"info\", data={\"invoice_id\": invoice_id})\n return {\"ok\": True, \"invoice_id\": invoice_id}\n"
}
JSON

200Returns the updated function. A request that changes no versioned field also returns 200, with status set to error.

Saving without changing anything records no version, and the response reports No changes detected, version unchanged rather than an error status.

Creating and editing functions is not available in the JavaScript or Python SDKs. Use REST or Console.

Find a function you saved​

List the functions in an app when you need a slug:

functions = client.functions.list()

Read one function to see its current code and version:

one = client.functions.get("FUNCTION_SLUG")

Review versions and restore one​

Read the history to see what changed and when. Each entry carries a history_id, which is what revert takes.

GET/api/apps/$TARUVI_APP_SLUG/functions/$FUNCTION_SLUG/history/
curl "$TARUVI_SITE_URL/api/apps/$TARUVI_APP_SLUG/functions/$FUNCTION_SLUG/history/" \
-H "Authorization: Api-Key $TARUVI_API_KEY"

200Returns history records newest first, each with a history_id used by revert.

Revert restores code and filter conditions only

Other versioned fields — including webhook_url, headers, and config — keep their current values, so reverting a function whose configuration changed since that version produces a combination that never existed. Read the history for changes to those fields first. See Versioning.

POST/api/apps/$TARUVI_APP_SLUG/functions/$FUNCTION_SLUG/revert/
curl -X POST "$TARUVI_SITE_URL/api/apps/$TARUVI_APP_SLUG/functions/$FUNCTION_SLUG/revert/" \
-H "Authorization: Api-Key $TARUVI_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{
"history_id": 12
}
JSON

200Restores code and filter_conditions only, and creates a new version rather than rewinding the counter.

Reverting creates a new version rather than rewinding the counter, so the history stays append-only.

Verify​

Execute the function once and confirm it returns what you expect. See Execute a function.

If the save is rejected, the message names the cause — most often the signature check or a compilation error. See Troubleshooting.