Skip to content

Context API

run(ctx) receives one argument, ctx.

PropertyHook typeDescription
ctx.httpPULL, PUSHHTTP client
ctx.secretsPULL, PUSHThe integration's credentials
ctx.orgPULL, PUSHOrganisation metadata
ctx.kvPULL, PUSHKey-value store scoped to the hook
ctx.logPULL, PUSHLog entries on the execution record
ctx.metaPULLPagination state from the previous page
ctx.eventPUSHThe change that triggered the run

ctx.http

ts
ctx.http.get(url, options?)
ctx.http.delete(url, options?)
ctx.http.post(url, body, options?)
ctx.http.put(url, body, options?)
ctx.http.patch(url, body, options?)

Each method returns a response. Use await.

js
const resp = await ctx.http.get('https://hr.example.com/api/v1/employees', {
  headers: { Authorization: `Bearer ${ctx.secrets.API_KEY}` },
  query: { limit: '100' },
});
if (resp.status !== 200) throw new Error(`HR API returned ${resp.status}`);
const employees = resp.body.data;

Arguments

ArgumentTypeDescription
urlstringAbsolute http: or https: URL.
bodyanypost, put and patch only. A string is sent as it is; any other value is sent as JSON.
options.headersobjectRequest headers, as strings. A User-Agent header is ignored.
options.queryobjectQuery parameters, as strings. Each replaces a parameter of the same name already in url.
options.timeoutnumberMilliseconds. Defaults to 60000, which is also the maximum.

When a request has a body and no Content-Type header, Content-Type: application/json is added.

Every request is sent with User-Agent: Flowstate-CustomIntegration/1.0.

Response

PropertyTypeDescription
statusnumberHTTP status code.
headersobjectResponse headers. Names are lower case.
bodyanyParsed JSON when the content-type header contains application/json and the body parses. Otherwise the body as a string.

A non-2xx status is returned, not thrown. Check status.

Errors

A call throws when:

  • the run has used its 50 requests (per page for PULL, per run for PUSH). Every call counts, including calls that throw.
  • the URL isn't a valid http: or https: URL.
  • the destination is a private network, localhost or a cloud metadata endpoint.
  • the server responds with a redirect. Redirects aren't followed.
  • the response is larger than 10 MB.
  • the request times out or the connection fails.

Each request made is listed on the execution's HTTP Log with its method, URL, status and duration.

ctx.secrets

A plain object holding the integration's credentials, keyed by credential key.

js
const token = ctx.secrets.API_KEY;
  • Keys are UPPER_SNAKE_CASE: a capital letter, then capitals, digits or underscores.
  • Values are strings. A key that isn't set is undefined.
  • A changed value applies from the next run.
  • Secret values that appear in log messages, log data, error messages or logged URLs are replaced with [REDACTED]. Values shorter than three characters aren't masked.

Credentials are managed in the app. See Store credentials.

ctx.org

Read-only.

PropertyTypeDescription
idstringOrganisation ID
namestringOrganisation name
timezonestringIANA time zone, such as Europe/London
currencystringReporting currency, ISO 4217, such as GBP

ctx.kv

A string key-value store that persists between runs.

js
const cursor = await ctx.kv.get('cursor');   // string or null
await ctx.kv.set('cursor', nextCursor);      // expires after 90 days
await ctx.kv.set('lock', '1', 3600);         // expires after 3,600 seconds
MethodReturnsDescription
get(key)string or nullnull when the key is missing, has expired, or holds an empty string.
set(key, value, ttlSeconds?)Stores value, replacing any existing value and its expiry.
RuleDetail
ScopeOne store per hook. Dry runs and real runs share it.
Keys1–256 characters. Anything else throws.
ValuesStrings of up to 64 KB (65,536 bytes as UTF-8). A non-string or larger value throws. Use JSON.stringify for structured data.
ExpiryttlSeconds in whole seconds. Omitted or 0: 90 days.
DeletingThere's no delete. Overwrite the value, or set a short ttlSeconds.

ctx.log

js
ctx.log.info('Fetched page', { page: 3, count: 100 });
ctx.log.warn('Employee has no email; skipped', { id: 'E-1042' });
ctx.log.error('Unexpected response', { status: resp.status });
ArgumentTypeDescription
messagestringConverted to a string.
dataanyOptional. Must be JSON-serialisable.

Each entry is stored with a timestamp and level (info, warn or error), and shown on the Console tab and in Execution History. Output from console isn't captured.

ctx.meta

PULL hooks only. The meta object the previous page returned, or undefined on the first page. See Pagination.

undefined in PUSH hooks.

ctx.event

PUSH hooks only. The change that triggered the run.

PropertyTypeDescription
entityTypestringThe hook's entity type
entityIdstringFlowstate ID of the changed record
changeTypestringcreate, update or delete
beforeobject or nullThe record before the change. null for create.
afterobject or nullThe record after the change. null for delete.

What before and after contain for each entity type: PUSH hooks.

undefined in PULL hooks.

Globals

Standard JavaScript built-ins such as JSON, Math, Date, Promise and Intl are available.

These aren't: fetch, setTimeout, URL, TextEncoder, atob, crypto, Buffer, structuredClone, require and process. Use ctx.http for network requests.

Flowstate Documentation