What a Function Returns

Declare the fields a function sends back. Apps and the Designer then read each one as what it is -- a number, true or false, a date -- and every call is checked against it.

Why declare it

A function can return anything, so without a declaration its result is read as text. You can show it, but the Designer cannot let a field turn a button off, show a section only when it is true, or take part in a calculation: it cannot prove what type the field is.

Declaring the fields removes that guesswork. A quote function that returns a total, whether it is paid and when it is due can then drive a Pay button that turns off once paid is true, and a line that shows only while total is more than 0.

Declare it in the dashboard

Open the function in Functions. Under Who can call is Returns. Choose Edit, add each field the function sends back with its type, and save. It takes effect at once, with no redeploy, and a later deploy keeps it.

TypeHolds
TextWords: a name, a status, a code.
NumberA number: a total, a count, a rating.
True / falseA yes or no: paid, available, verified.
Date and timeAn ISO-8601 date and time, or a date alone: when it is due.

Names start with a letter, then letters, digits or _; a function declares up to 30. Lists and objects are not declared -- their type is not one value. Clearing every field goes back to declaring nothing.

index.ts
TypeScript
export async function handler(ctx) {
  // Declared in the dashboard: total (Number), paid (True / false), due (Date and time)
  return { total: 120, paid: false, due: '2026-12-01T18:00:00Z' }
}

In the Designer

A Call a function step that keeps its result offers that function's declared fields, each with its type, everywhere a value is picked. A true/false field can drive Disabled, Selected, Visible or a condition; a number can go into a calculation. A field the function does not declare is refused, so a misspelt name is caught while designing rather than in the app.

The Designer reads what each function declares from your project when it opens and again just before each export, so an export always uses what the project says now. Your saved design does not change when a declaration does.

When a response does not match

Every call from an app is checked against the declaration. A declared field that is missing, or of another type, is recorded on that call's entry in the Logs tab, in plain words:

Logs
text
Didn't match what it returns: total is text, not a number; due is missing

The response still reaches the app

A mismatch never blocks the call: the app gets exactly what the function returned, and reads a field it cannot use as empty. That keeps a live app working while code and declaration catch up with each other -- the log tells you which one to fix.

A field sent as null matches -- a field may be empty. Fields the declaration does not list are not checked. Calls from triggers and crons return to no app, so they are not checked.

Snapshots and the API

A project snapshot carries each function's declaration, so cloning or promoting a project brings it along. A snapshot taken before a function declared anything keeps whatever the destination has.

Terminal
Bash
curl -X PUT https://api.koolbase.com/v1/projects/$PROJECT_ID/functions/quote/response-shape \
  -H "Authorization: Bearer $ADMIN_KEY" -H "Content-Type: application/json" \
  -d '{"fields":[{"name":"total","type":"num"},{"name":"paid","type":"bool"},{"name":"due","type":"datetime"}]}'

Types are string, num, bool and datetime. {"fields": []} clears the declaration.