About functions

What OmniLab functions are, how they run, when to use one instead of a webhook, and the limits your code works within.

4 min read

A function is a small piece of TypeScript that runs on OmniLab's own infrastructure. You write it in Studio and OmniLab compiles it. From then on the platform runs it for you: when something happens in a campaign, or at a decision point such as a contact signing up.

You need no server, no endpoint, and no deployment of your own.

Functions are configured under Enterprise Settings, which needs an Admin role with the Global organisation selected. Confirm you have that access before planning work: the tab is hidden without it.

How it works

You store one TypeScript file with one exported handler. When you build it, OmniLab compiles that file to a WebAssembly module and keeps the compiled version. Every invocation from then on loads it into a fresh sandbox and calls your export.

The shape of a platform event function
import type { PlatformEventHandler } from "./omnilab";

export const onPlatformEvent: PlatformEventHandler = (event) => {
  console.log("Something happened: " + event.type);
};

Your handler reaches the outside world through the calls OmniLab provides: read a config value, read a secret, make an HTTP request to a host you have allow-listed, read a contact, and write contact custom fields. The set is deliberately small, which is what makes your code safe to run on the platform. It is enough for most integration work.

Each invocation is independent. Nothing you set on one call carries over to the next. Keep what you need in contact custom fields, or in your own system over HTTP.

Functions or webhooks?

Both let you react to what happens in OmniLab. The difference is where your code runs and whether it can change the outcome.

FunctionWebhook
Runs onOmniLab's infrastructureYours
You need to hostNothingAn HTTPS endpoint
Can change what OmniLab doesYes, for one kindNo
Best forLogic that must run inside an OmniLab operation, or small integrations you would rather not hostFeeding a system you already run

A webhook tells your systems that something happened, after OmniLab has already decided it. A function runs inside OmniLab. One of the two kinds runs inside the decision itself, so it can reject a sign-up, normalise an email before it is stored, or send a verification message through your own provider.

Choose a kind

Every function is one of two kinds, and the kind decides when it runs and what it can affect. It is fixed when you create the function, so make this choice before you start writing.

Platform event functionHook function
RunsAfter something happenedDuring an operation, which waits for it
Can it change the outcome?NoYes — it continues or refuses
Your exportonPlatformEventon + the hook point, for example onContactCreatePre
Wired up byA subscription to event typesA binding to a hook point
Your return valueDiscardedThe decision OmniLab acts on
If it failsThe activity is unaffectedThe operation is refused: see what a hook guarantees

Start with a platform event function when either would work. It cannot break anything a customer is doing. Getting it wrong costs a missing side effect, not a failed sign-up.

Use a platform event function to react to activity: enrich a contact, push to your CRM, notify a channel. Use a hook function to vet a sign-up, normalise data before it is stored, or send verification mail.

Changing the kind means starting again

The kind determines the export your code must provide, which tabs appear in the editor, and the payload the test runner sends. There is no way to convert one kind into another: you create a new function and delete the old one.

From draft to running

Saving and building are separate on purpose. Saving stores your code and type-checks it; it never changes what is running. Only a build produces a new compiled version.

Create Build build succeeds build fails, nothing was live build fails, previous version kept Build again Save new source, Build again Delete Delete Delete Draft Building Ready BuildFailed Deleted

The status in the function list is one of Draft, Building, Ready, Build failed, or Deleted. Only a Ready function runs.

The two paths out of Building are worth knowing. A function that has never built successfully goes to Build failed. A live function that fails a rebuild returns to Ready and keeps serving its previous version. A broken rebuild never takes a working function offline.

What your code works within

Your code is one TypeScript file, user.ts. A function with an empty allow-list makes no outbound calls. Each invocation has a fixed time, memory and SDK call budget, listed under Limits.

Two rules catch people out. Secrets never go in your source — you store them in a bundle, bind the bundle to the function, and read them by name at runtime. And contact custom field keys beginning system. or feature. are reserved, so writes to them are rejected.

Next steps

On this page