Advanced action flows API reference (EAP)

Advanced action flowsare code-based automated workflows that run in isolated environments referred to as anadvanced action flow sandbox. This article describes every global available for use in advanced action flow code, with signatures, parameters, limits, and examples.


What's my plan?







All Suites

Growth, Professional, Enterprise, or Enterprise Plus







Summary: ◀▼
Advanced action flows let you automate workflows using JavaScript in isolated sandboxes with access to ticket, user, custom object, and asset data. You can make HTTP requests, call AI agents, pause execution, store data persistently, manage approvals, and handle files. This API supports complex automation with triggers, conditions, and integrations, helping you customize and extend your support processes effectively.




Advanced action flows are code-based automated workflows
that run in isolated environments referred to as an advanced action flow sandbox.
This article describes every global available for use in advanced action flow code, with
signatures, parameters, limits, and examples.
This article contains the following topics:
Advanced action flow sandbox globals
Inputs
Outputs
Console
HTTP requests
AI calls
Pause and sleep
Storage
Tickets
Users
Custom objects
ITAM assets
Approvals
Task lists
Parsing and generating files
Decrypting secrets
Cryptography
Calling actions, action flows, and agents
Account
Advanced action flow trigger condition syntax



Related articles
Creating advanced action flows
Editing and managing advanced action
flows
Monitoring and troubleshooting advanced
action flows




Advanced action flow sandbox globals

Advanced action flow code runs in isolated JavaScript environments built on standard
ECMAScript with the following set of platform globals injected. It is neither
Node.js nor a browser.
All standard JavaScript built-ins are available: Object,
Array, Map, Set,
Promise, JSON, Math,
Date, RegExp, Intl, typed
arrays, async/await, and generators. Additionally,
the polyfills TextEncoder, TextDecoder,
atob, btoa, URL,
URLSearchParams, and FormData.
The following JavaScript functions aren't available: require,
import, process, fs,
child_process, buffer,
window, document, eval,
proxy, reflect, WeakMap,
WeakSet, WeakRef,
SharedArrayBuffer, and WebAssembly.
The following advanced action flow globals are included:








Global
Description




input
Advanced action flow trigger input and resume data.


output
The workflow's return value.


fetch
Low-level HTTP.



http, HttpClient

JSON-oriented HTTP client.


connections
Authenticated clients for registered services.


agents
AI steps (agents.run) and custom
agents.


approvals
Create approval requests.


sleep
Brief in-execution delay.


pause
Stop and resume execution later.


storage
Durable key-value storage that persists after pauses and
failed executions.


tickets
Zendesk tickets.


users
Zendesk users.


objects
Zendesk custom object records.


assets
ITAM asset records.


taskLists
Task list templates.



actions, workflows

Invoke catalog actions and other action flows.


data
Parse and generate CSV, XML, XLSX, ZIP, or compressed
data.


secrets
Decrypt stored credentials.


crypto
Web cryptography.


accounts
Current account context.


console
Logging to the execution history.








Inputs

Inputs hold the data your advanced action flow was invoked with. The details vary by
the type of advanced action flow trigger.








Advanced action flow trigger
Input




Manual
One property per declared parameter.


Ticket event

ticket_id and event metadata.


User event

user_id and event metadata.


Custom object event

record_id, objectType, and
event metadata.


Web
The parsed request body.


Action catalog
The input object supplied by the caller.


After an approval pause

approval_result with the decision.





For example: const ticket = await tickets.get(input.ticket_id);



Outputs

Outputs are what an AI agent or called action flow receives when invoked by an
advanced action flow. Assign an output to return a value.
For
example: output.assetTag = asset.tag;
output.status = 'provisioned';


Serialized output must not exceed 2 MB.



Console

console.log, console.info,
console.warn, and console.error write to the
Console tab of each advanced action flow's execution history. Events are captured
with timestamps and level colors. Objects are rendered as expandable trees.
Example: console.log('Processing ticket', { id: ticket.id, priority: ticket.priority });




HTTP requests

The following HTTP calls are used:
http and HttpClient
connections.<name>
fetch




http and HttpClient

http and HttpClient are the JSON-oriented
client. Bodies are serialized to JSON automatically, JSON responses are parsed
automatically, and a non-2XX response throws an error carrying the
status, statusText, and
body so you can branch on the status without re-reading the
response.
Examples: http.get(path, headers)
http.post(path, body, headers)
http.put(path, body, headers)
http.patch(path, body, headers)
http.delete(path, headers)
http.request(method, path, body, headers)


try {
const user = await http.get('https://api.example.com/v1/users/42');
console.log(user.email);
} catch (err) {
if (err.status === 404) {
console.warn('User not found');
} else {
throw err;
}
}

To bind a base URL or a connection, construct an
HttpClient: const api = new HttpClient({ baseUrl: 'https://api.example.com/v1' });
const user = await api.get('/users/42');




connections.<name>


connections.<name> is an HttpClient
bound to a registered connection in your account. Authentication is attached
automatically.
Example: await connections.slack.post('/api/chat.postMessage', {
channel: '#it-alerts',
text: 'Provisioning complete.',
});

const issue = await connections.jira.post('/rest/api/3/issue', {
fields: {
project: { key: 'IT' },
summary: `Asset request from ticket ${ticket.id}`,
issuetype: { name: 'Task' },
},
});




fetch

For cases the JSON client doesn't cover, such as non-JSON payloads, binary
responses, or fine-grained header control, use the standard
fetch semantics.
The following limits apply:

Request body: 48 MB

Concurrent requests per execution: 8

Automatic retries: Up to 5 on HTTP 5XX and 429 errors, with
backoff
Zendesk APIs must be allowed and the advanced
action flow creator must have permissions to interact with the
records.


Example: const res = await fetch('https://api.example.com/v1/report.csv', {
method: 'GET',
headers: { Accept: 'text/csv' },
});

if (!res.ok) throw new Error(`Report fetch failed: ${res.status}`);
const csv = await res.text();





AI calls

To call AIs within an advanced action flow, use agents.run(request).
This is a single run-time AI primitive.









Parameter
Type
Description




prompt
string
Required. The instruction and content.


instructions
string
Optional. System-level guidance.


files
array
Optional. {name, content} entries.
content accepts a
Uint8Array, ArrayBuffer,
typed array, data URI, or base64 string.


output.schema
object
Optional. A JSON schema forcing structured output. Use
whenever the workflow branches on the result. If no schema is
supplied, returns a string.






No schema example (plain
text): const summary = await agents.run({
prompt: `Summarize this support conversation in two sentences.\n\n${thread}`,
});

Structured output
(schema): const triage = await agents.run({
instructions: 'You are a support triage assistant. Be conservative.',
prompt: `Classify this ticket.\n\nSubject: ${ticket.subject}\n\n${ticket.description}`,
output: {
schema: {
type: 'object',
properties: {
category: { type: 'string', enum: ['billing', 'technical', 'sales', 'other'] },
sentiment: { type: 'string', enum: ['positive', 'neutral', 'negative'] },
urgent: { type: 'boolean' },
},
required: ['category', 'sentiment', 'urgent'],
},
},
});

if (triage.urgent) {
await tickets.update(ticket.id, { priority: 'urgent' });
}

Example omnichannel routing from an
attachment: const res = await fetch(attachment.content_url);
const bytes = new Uint8Array(await res.arrayBuffer());

const invoice = await agents.run({
prompt: 'Extract the invoice number, issue date, and total amount.',
files: [{ name: attachment.file_name, content: bytes }],
output: {
schema: {
type: 'object',
properties: {
invoiceNumber: { type: 'string' },
issueDate: { type: 'string' },
total: { type: 'number' },
},
required: ['invoiceNumber', 'total'],
},
},
});




Pause and sleep

Pauses ends an advanced action flow's execution, while sleep is a wait of defined
duration that is built into a workflow. Pauses aren't counted against the execution
timeout, but sleep is. Therefore, sleep should only be used for delays of a few
seconds or less.


pause

Advanced action flows can be configured to resume after a pause when specific
events occur or conditions are met.








Type
Waits for




pause()
Indefinitely, until an explicit resume is
received


pause(durationMs)
A timer, up to 30 days


pause({event, condition})
A Zendesk event matching a JMESPath condition


pause({event: 'approval', approval_id,
ticket_id})
An approval decision


pause({event: 'workflow-complete',
execution_id})
An invoked workflow to finish


pause({event: 'agent-complete',
execution_id})
An invoked custom agent to finish





Example: // Wait 24 hours.
pause(24 * 60 * 60 * 1000);

// Wait for the ticket to be solved.
pause({ event: 'ticket-updated', condition: "status == 'solved'" });




sleep

Use sleep() to build a short wait into an advanced action flow, such as
backing off between requests.
Example: for (const record of records) {
await pushRecord(record);
await sleep(200);
}





Storage

Use storage.get(key, options) and storage.set(key, value,
options) to store values that need to persist across executions and
survive updates to the advanced action flow.









Parameter
Type
Description




key
string
Required. Can't be empty. Maximum 255
characters. storage.get returns
unidentified if the key is
missing.



value
string
Required for storage.set and must be a
string. Objects must be serialized.


options.scope
string

'workflow' (default) or
'account'.





Example: // Track a cursor across scheduled runs.
const since = (await storage.get('last_sync')) ?? '1970-01-01T00:00:00Z';
const changed = await fetchChangedSince(since);
await storage.set('last_sync', new Date().toISOString());

// Store an object.
await storage.set('counts', JSON.stringify({ processed: 42 }));
const counts = JSON.parse((await storage.get('counts')) ?? '{}');

// Share a value across all flows in the account.
await storage.set('escalation_channel', '#urgent', { scope: 'account' });




Tickets

Use tickets to get, create, update, delete, search, list, and get or
add task lists on tickets.
To make them easier to work with, custom ticket fields are flattened to named
properties on read and re-nested on write. For
example: const ticket = await tickets.get(input.ticket_id);
console.log(ticket.subject, ticket.priority, ticket.department);

await tickets.update(ticket.id, {
priority: 'high',
tags: [...ticket.tags, 'escalated'],
department: 'Finance', // a custom field, by name
comment: { body: 'Escalated automatically.', public: false },
});


ticket.create() supplies a default initial comment if you don't
specify one and accepts comment as a plain
string: const created = await tickets.create({
subject: 'Laptop refresh required',
comment: 'Raised automatically by the inventory flow.',
requester_id: user.id,
});


ticket.search() and ticket.list() return
asynchronous iterators that page
automatically: for await (const t of tickets.search({ query: 'type:ticket status:open tags:new-hire' })) {
await tickets.update(t.id, { priority: 'normal' });
}

Tip: Unbounded for
await over a large search can exhaust the execution timeout. To
avoid this, count as you go and stop at a sensible bound, saving a cursor to
storage for the next
execution.




Users

Use users to get, create, update, delete, list, and search for
users.
There are two unique user properties related to advanced action flows:








Property
Description




users.creator
The admin who created the advanced action flow. All Zendesk
calls run as this user.


users.runner
The user who triggered the current execution of the advanced
action flow.





Example: await tickets.update(ticket.id, {
comment: { body: `Run for ${users.runner.name}.`, public: false },
});

To make them easier to to work with, custom user fields are flattened to named
properties on read and re-nested on write.

user.list() accepts only role,
permissionSet, and external_id as server-side
filters. For lookups by email or free text, use users.search()
instead. for await (const u of users.search({ query: 'email:sam@example.com' })) {
await users.update(u.id, { organization_id: org.id });
}




Custom objects

Use objects.<TypeName> to get, list, search, create,
update, and delete custom object records.
To make them easier to work with, object type names resolve on first use, and custom
object fields are flattened to named properties on read and re-nested on write.
Example: const expense = await objects.Expense.get(input.record_id);

if (expense.amount > 100) {
await objects.Expense.update(expense.id, { status: 'pending_approval' });
}




ITAM assets

Use assets.<TypeName> to manage assets.
Example: const laptops = [];
for await (const a of assets.Laptop.search({ query: 'status:unassigned' })) {
laptops.push(a);
}

if (laptops.length < 50) {
await connections.slack.post('/api/chat.postMessage', {
channel: '#it-inventory',
text: `Only ${laptops.length} unassigned laptops remain.`,
});
}




Approvals

Create approval requests in Zendesk with approvals.create():









Parameter
Type
Description




ticketId
number
Required. The ticket the approval request belongs to.


title
string
The approval subject.


description
string
The message shown to the approver.


approver
object
{type: 'user' | 'group', id}





Returns the created approval, including its
ID: const approval = await approvals.create({
ticketId: ticket.id,
title: `Approve expense of $${invoice.total}?`,
description: `Submitted by ${requester.name}.`,
approver: { type: 'user', id: manager.id },
});

pause({ event: 'approval', approval_id: approval.id, ticket_id: ticket.id });

// Resumes here after the decision.
if (input.approval_result.status === 'approved') {
await tickets.update(ticket.id, { status: 'solved' });
}




Task lists

taskLists operates on admin-defined task list templates. You can
get, list, create, update, and delete the task lists. taskLists.get
includes the template's tasks, while taskLists.list omits each
template's tasks.
If you need to access a ticket's task list, you must use
tickets.getTaskList(ticket.id): for await (const template of taskLists.list()) {
if (template.name === 'IT Onboarding') {
await tickets.addTaskList(ticket.id, template.id);
}
}

const attached = await tickets.getTaskList(ticket.id);




Parsing and generating files

Imports aren't possible for advanced action flows. Instead, you must use the
following utilities to generate and parse files.
You can parse and generate a maximum of 10,000 rows per operation.








Method
Description




data.csv.parse(text, options)
Parse CSV to rows


data.csv.stringify(rows, options)
Generate CSV



data.tsv.parse /
data.tsv.stringify

Tab-separated equivalents


data.xml.parse(text, options)
Parse XML to an object


data.xml.stringify(values, options)
Generate XML


data.xlsx.parse(bytes, options)
Read a spreadsheet


data.xlsx.build(sheets, options)
Create a spreadsheet



data.gzip(bytes) /
data.gunzip(bytes)

gzip



data.deflate(bytes) /
data.inflate(bytes)

Deflate


data.zip.list(bytes)
List archive entries


data.zip.extract(bytes, names)
Extract entries


data.zip.create(entries, options)
Create an archive





Additionally, PDF, DOCX, and PPTX generation is also available through the platform.
Use the AI chat to generate the correct API call for your use case if you need to
generate one of these file types.
Examples: const res = await fetch(attachment.content_url);
const csv = await res.text();
const rows = await data.csv.parse(csv, { header: true });

for (const row of rows) {
await objects.Employee.create({
name: row.full_name,
email: row.email,
department: row.dept,
});
}
const bytes = new Uint8Array(await (await fetch(zipUrl)).arrayBuffer());
const entries = await data.zip.list(bytes);
const extracted = await data.zip.extract(bytes, entries.map((e) => e.name));




Decrypting secrets

When connecting to external systems that use API keys or bearer token authentication,
the key is stored as an encrypted secret. Use secrets.decrypt to
decrypt a cfsec:v1: value that is automatically created when you
provide an API key into the AI chat when creating or updating an advanced action
flow.
Encryption is bound to your account. A value from one account can't be decrypted in
another account. Decryption failures return a deliberately unspecific error so trace
logs can't be used to probe the value.
Never store credentials directly in the code of an advanced action flow. The code is
stored in version history and visible to every admin who can open the workflow.
Example: const apiKey = await secrets.decrypt(STRIPE_API_KEY);

const charge = await http.post('https://api.stripe.com/v1/charges',
{ amount: 2000, currency: 'usd' },
{ Authorization: `Bearer ${apiKey}` },
);




Cryptography

Use standard web crypto: crypto.randomUUID,
crypto.getRandomValues(typedArray), and
crypto.subtle.* for digests, HMACs, and signature
verification.
Random values and timestamps are recorded so that resuming a paused workflow replays
identically.
Example: const requestId = crypto.randomUUID();

// Verify an inbound webhook signature.
const key = await crypto.subtle.importKey(
'raw',
new TextEncoder().encode(await secrets.decrypt(WEBHOOK_SECRET)),
{ name: 'HMAC', hash: 'SHA-256' },
false,
['verify'],
);




Calling actions, action flows, and agents

The following globals are available to invoke custom actions, action flows, other
advanced action flows, and custom agents:








Global
Description




actions.<name>
Invokes a custom action API and waits up to 5 minutes for its
output.


workflows.<name>
Invokes an action flow or advanced action flow, returning an
execution handle.


agents.<CustomAgent>
Invokes a custom agent, returning an execution
handle.


workflows.executions.get
Retrieves an execution's current state.





In the AI chat panel, enter a forward slash ( / ) to insert a reference to an
available action, agent, action flow, or advanced action flow. This passes the exact
identifier and schema to the AI.
Example: // Blocking: returns output directly.
const eligibility = await actions.validateCustomerEligibility({
customerId: ticket.requester_id,
});

if (eligibility.eligible) {
// Non-blocking: returns a handle.
const execution = await workflows.provisionAccount({ userId: ticket.requester_id });

// Wait for it to finish.
pause({ event: 'workflow-complete', execution_id: execution.id });

const finished = await workflows.executions.get(execution.id);
console.log('Child flow output:', finished.output);
}




Account

Use account.current to return the following properties about your
Zendesk account:








Property
Description




account.current.url
Your Zendesk instance URL


account.current.id
Your Zendesk account ID





Example: const ticketUrl = `${accounts.current.url}/agent/tickets/${ticket.id}`;

await connections.slack.post('/api/chat.postMessage', {
channel: '#managers',
text: `Negative sentiment detected: &lt;${ticketUrl}|Ticket #${ticket.id}&gt;`,
});




Advanced action flow trigger condition syntax

Advanced action flow trigger filters and event pauses use JMESPath, evaluated against
the event payload. The workflow runs or resumes only when the condition is
true.








Condition
Expression




Field equality
priority == 'high'


Two conditions
priority == 'high' && status !=
'solved'


Either condition
status == 'new' || status == 'open'


Array contains
contains(tags, 'new-hire')


Numeric literal

ticket_form_id == \360001234567 Wrap
numeric literals must be preceded by a backslashe. A numeric
value in quotes is treated as a string and won't match a
numeric field.



Field is set
custom_fields.department != null


Nested field
via.channel == 'email'


Negation
!(status == 'closed')







{
"@context": "https://schema.org",
"@type": "TechArticle",
"@id": "https://support.zendesk.com/hc/en-us/articles/11156518384922-Advanced-action-flows-API-reference-EAP",
"url": "https://support.zendesk.com/hc/en-us/articles/11156518384922-Advanced-action-flows-API-reference-EAP",
"headline": "Advanced action flows API reference (EAP)",
"description": "You can use advanced action flows to create and manage code-based automated workflows with a comprehensive API that supports inputs, outputs, HTTP requests, AI calls, storage, ticket and user management, approvals, and more within isolated JavaScript environments.",
"articleSection": "Product help",
"datePublished": "2026-08-21T10:32:40+00:00",
"dateModified": "2026-08-25T14:40:21.251203+00:00",
"inLanguage": "en-US",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://support.zendesk.com/hc/en-us/articles/11156518384922-Advanced-action-flows-API-reference-EAP"