﻿# Function Reference

This page provides a reference for all available function types and their configuration options.

## JSON Schema

Function definitions are part of the main Functions Framework schema, available [here](https://schemas.acrobits.net/core/functions/input.json).

---

## Format

A function definition is a JSON object with the following fields:

| Field | Required | Description |
|-------|----------|-------------|
| `id` | Yes | Unique identifier for the function. Must be a non-empty string of lowercase letters, numbers, and underscores (e.g. `my_awesome_function`). Other functions and Smart Links reference this ID. |
| `definition` | Yes | Declares what the function does. See [Definitions](#definitions) below. |
| `condition` | No | A [condition](conditions.md) evaluated whenever this function is invoked. If it evaluates to false, the function is not executed. Default: always true. |
| `exported` | No | If `true`, the function can be invoked from external callers such as [Smart Links](smart-links.md). Default: `false`. |

---

## Definitions

### Navigate

Navigates the user to another part of the application.

**Type:** `navigate`

| Field | Type | Description |
|-------|------|-------------|
| `path` | String | The app path to navigate to. Supports [placeholders](scopes.md#supported-placeholders). |

**Example use cases:** Display call-related information such as CRM data in the browser tab while on a call.

```json
{
    "@": "navigate",
    "path": "/browser/?callId=%callId%"
}
```

---

### Set Variable

Sets a variable in the current scope's memory bank.

**Type:** `setVariable`

| Field | Type | Description |
|-------|------|-------------|
| `name` | String | Variable name. Can include a scope prefix (see [Scopes](scopes.md)). |
| `value` | String | Value to assign. Supports [placeholders](scopes.md#supported-placeholders). |

```json
{
    "@": "setVariable",
    "name": "scope[myVariableName]",
    "value": "hello"
}
```

---

### Extract JSON Values

Extracts values from a JSON string using [JSONPath (RFC 9535)](https://www.rfc-editor.org/rfc/rfc9535) and saves them to the local scope.

If multiple nodes match the JSONPath expression, the first match is used.

**Value unescaping:** If the result is a JSON string, it is unescaped and formatted as a literal (e.g. `"\u2764"` becomes `❤`). If the result is `null`, a number, boolean, object, or array, it is formatted as a regular JSON value.

**Type:** `extractJsonValues`

| Field | Type | Description |
|-------|------|-------------|
| `value` | String | The JSON string to extract from. Supports [placeholders](scopes.md#supported-placeholders). |
| `mappings` | Array | Array of extraction mappings (see below). |

Each entry in `mappings`:

| Field | Type | Description |
|-------|------|-------------|
| `name` | String | Variable name to store the result. Can include a scope prefix. |
| `path` | String | JSONPath expression specifying which element to extract. |

```json
{
    "@": "extractJsonValues",
    "value": "{\"data\":{\"store\": \"1\"}}",
    "mappings": [
        {
            "name": "myVariableName",
            "path": "$.data.store"
        }
    ]
}
```

---

### HTTP Link

Opens a URL in the system's native browser.

**Type:** `link`

| Field | Type | Description |
|-------|------|-------------|
| `url` | String | The URL to open. Supports [placeholders](scopes.md#supported-placeholders). |

**Example use cases:** Display call-related information such as CRM data in the native browser while on a call.

```json
{
    "@": "link",
    "url": "https://google.com"
}
```

---

### Dial Action

Invokes a dial action from an account to a target URI.

**Type:** `dialAction`

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `uri` | String | — | Target URI. Supports [placeholders](scopes.md#supported-placeholders). |
| `accountId` | String | Scope-related account | Account that will invoke the dial action. If absent, derived from the current scope. |
| `dialAction` | Dial Action | Value of `dialActionOnTap` prefKey | The [dial action](../dialactions.md) to invoke. |

```json
{
    "@": "dialAction",
    "uri": "*scope[helloWorld]*"
}
```

---

### Send Linkup Message

Creates a direct message channel in Linkup messaging (if it does not already exist) and sends a message. The recipient must be specified as a cloud username. Cannot send SMS.

The function fails if Linkup Messaging is not configured or the recipient cannot be resolved.

**Type:** `sendLinkupMessage`

| Field | Type | Description |
|-------|------|-------------|
| `recipient` | String | Cloud username of the recipient. Supports [placeholders](scopes.md#supported-placeholders). |
| `message` | String | Message text. Supports [placeholders](scopes.md#supported-placeholders). |

```json
{
    "@": "sendLinkupMessage",
    "recipient": "JohnDoe",
    "message": "Hello John, I like your style!"
}
```

!!! note "Added in 25.3"

---

### Send Linkup SMS Message

Creates a direct SMS channel in Linkup messaging (if it does not already exist) and sends an SMS message. The recipient must be specified as a phone number. Cannot send non-SMS messages.

The function fails if Linkup Messaging is not configured, the recipient cannot be resolved, or there are no outbound phone numbers for SMS on the server.

**Type:** `sendLinkupSmsMessage`

| Field | Type | Description |
|-------|------|-------------|
| `recipient` | String | Phone number in normalized format (e.g. `+420123456789`). Supports [placeholders](scopes.md#supported-placeholders). |
| `message` | String | Message text. Supports [placeholders](scopes.md#supported-placeholders). |

```json
{
    "@": "sendLinkupSmsMessage",
    "recipient": "+420123456789",
    "message": "Hello John, I like your style!"
}
```

!!! note "Added in 25.3"

---

### Create and Open Linkup Channel

Creates a direct channel and navigates to it in the Linkup messaging tab.

**Type:** `createAndOpenLinkupChannel`

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `cloudUsername` | String | `null` | Cloud username to open the channel with. |
| `uri` | String | `null` | URI to open the channel with. |

```json
{
    "@": "createAndOpenLinkupChannel",
    "cloudUsername": "user_1"
}
```

!!! note "Added in 25.3"

---

### Open Linkup Channel

Opens an existing Linkup channel in the messaging tab.

**Type:** `openLinkupChannel`

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `streamId` | String | — | Stream ID to open. |
| `messageId` | String | `null` | Message ID to scroll to. |

```json
{
    "@": "openLinkupChannel",
    "streamId": "123"
}
```

!!! note "Added in 25.3"

---

### Web Request

Makes an HTTP request. The configuration is similar to the Web Service Definition format with additional fields for saving response data.

**Type:** `webRequest`

All standard Web Service Definition fields are supported, plus:

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `save/headers` | Object | — | Maps response header names to scope variable names. |
| `save/body` | String | — | Scope variable name to store the response body. |
| `save/statusCode` | String | — | Scope variable name to store the HTTP status code. |

**Example use cases:** Call telemetry. Invoke custom call actions such as server-side audio recording.

**Simple GET request:**

```json
{
    "@": "webRequest",
    "url": "https://example.com/recording/%account[cloud_username]%/%account[cloud_password]%",
    "method": "get"
}
```

**POST request with JSON body:**

```json
{
    "@": "webRequest",
    "url": "https://example.com/recording",
    "method": "post",
    "body": {
        "data": "{\"username\": \"%account[cloud_username]%\", \"password\": \"%account[cloud_password]%\"}",
        "content-type": "application/json"
    }
}
```

**Saving response data:**

```json
{
    "@": "webRequest",
    "url": "https://example.com/api",
    "method": "post",
    "save": {
        "headers": {
            "X-My-Data": "myDataValue",
            "X-My-Data-2": "myDataValue2"
        },
        "body": "myBody",
        "statusCode": "myStatusCode"
    }
}
```

**Custom headers with SSO authentication:**

```json
{
    "@": "webRequest",
    "url": "https://example.com/api",
    "method": "post",
    "headers": {
        "x-my-header": "%platform%",
        "%account[thingy]%": "wut?"
    },
    "auth": {
        "type": "sso",
        "ssoHeader": "x-cs-auth-token",
        "ssoFormat": "plain"
    }
}
```

---

### DTMF

Sends a DTMF sequence during an active call.

**Type:** `dtmf`

| Field | Type | Description |
|-------|------|-------------|
| `dtmfSequence` | String | The DTMF sequence to dial. |

**Example use cases:** Invoke custom call actions such as call park or server-side audio recording.

```json
{
    "@": "dtmf",
    "dtmfSequence": "#5"
}
```

---

### Delay

Invokes a function after a specified delay.

**Type:** `delayed`

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `function` | Function request | — | The function to invoke after the delay. |
| `hours` | Integer | `0` | Delay hours. |
| `minutes` | Integer | `0` | Delay minutes. |
| `seconds` | Integer | `0` | Delay seconds. |
| `milliseconds` | Integer | `0` | Delay milliseconds. |

**Example use cases:** Wait for other events not tracked by the Functions Framework to complete, such as app screen transitions.

```json
{
    "@": "delayed",
    "seconds": 1,
    "milliseconds": 250,
    "function": {
        "id": "openBrowser"
    }
}
```

---

### Log

Writes a message to the application log.

**Type:** `log`

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `message` | Translatable string | — | Log message. The `args` array supports [placeholders](scopes.md#supported-placeholders). |
| `level` | `Debug`, `Info`, `Warning`, `Error` | `Info` | Severity level. |

```json
{
    "@": "log",
    "message": {
        "raw": "Call %s started with direction %s",
        "args": [
            "%callId%",
            "%callDirection%"
        ]
    },
    "level": "Debug"
}
```

---

### Logout

Starts the app reset or logout flow.

**Type:** `logout`

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `mode` | `reset`, `logout` | `logout` | Which flow to invoke. |
| `attended` | Boolean | `false` | Whether to show an interactive confirmation dialog. |

**Example use cases:** Log a user out of the app. Log a user out of the app from an interactive push flow.

```json
{
    "@": "logout",
    "mode": "reset",
    "attended": true
}
```

!!! note "Added in 26.1"

---

### Notification

Fires a local notification from the app.

**Type:** `notification`

| Field | Type | Description |
|-------|------|-------------|
| `definition` | Object | Notification configuration (see below). |

| `definition` field | Type | Description |
|---------------------|------|-------------|
| `title` | String | Notification title. |
| `message` | String | Notification body text. |

```json
{
    "@": "notification",
    "definition": {
        "title": "Title",
        "message": "Message"
    }
}
```

---

### Hangup

Hangs up or rejects the active call, the call in scope, or all calls in the active/scoped group.

**Type:** `hangup`

No fields.

```json
{
    "@": "hangup"
}
```

---

### Answer

Answers an incoming call or a call in scope.

**Type:** `answer`

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `intent` | `auto`, `noOutgoingVideo`, `videoBothWays` | `auto` | Media intent to answer the call with. Unrecognized values default to `videoBothWays`. |

**Example use cases:** Answer a video call with `noOutgoingVideo` intent.

```json
{
    "@": "answer",
    "intent": "noOutgoingVideo"
}
```

---

### Reject

Rejects an incoming call or a call in scope.

**Type:** `reject`

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `mode` | Object | Reject with `486 Busy Here` | Rejection mode configuration (see examples below). |

**Example use cases:** Reject the call in various modes.

**Reject here (486 Busy Here):**

```json
{
    "@": "reject",
    "mode": {
        "where": "here",
        "reason": {
            "Reason": "User",
            "Description": "IPC"
        }
    }
}
```

**Reject with explicit response code:**

```json
{
    "@": "reject",
    "mode": {
        "where": "explicit",
        "byUserAction": true,
        "responseCode": "451",
        "phrase": "Unavailable for legal reasons",
        "warning": "Agreement not accepted"
    }
}
```

---

### Toggle Mute

Mutes or unmutes the microphone. This is a global option — it affects all calls and does not require a call scope.

**Type:** `toggleMute`

No fields.

```json
{
    "@": "toggleMute"
}
```

---

### Toggle Hold

Holds or unholds the active call or a call in scope. For groups, it sets the group active or inactive. If no call scope is specified, the active group is deactivated. If there's no active group a random group with at least one non-teminal call is activated.

**Type:** `toggleHold`

No fields.

```json
{
    "@": "toggleHold"
}
```

---

### Toggle Record

Starts or stops recording the active group or a group in scope.

**Type:** `toggleRecord`

No fields.

```json
{
    "@": "toggleRecord"
}
```

---

## Function Sequences

Function sequences follow structured concurrency principles. A sequence completes only when all of its nested functions complete.

### Overview

| Type | Execution | Completes when | Skips on | Use when |
|------|-----------|----------------|----------|----------|
| [Function Sequence](#function-sequence) | Sequential | End of list | — | You want to run all valid steps |
| [First Function Of](#first-function-of) | Sequential | First success | Success | Any one valid action is sufficient |
| [Function Sequence Until](#function-sequence-until) | Sequential | First failure | Failure | Steps depend on each other |
| [Parallel Functions](#parallel-functions) | Parallel | Depends on `await` | Depends on `await` | Independent functions should run concurrently |

---

### Function Sequence

Invokes functions in order. Each function's condition is checked; if true, the function executes.

```
for function in functions:
    if function.condition():
        function.execute()
```

**Type:** `functionSequence`

| Field | Type | Description |
|-------|------|-------------|
| `sequence` | Array of function requests (min 2) | Functions to invoke in order. |

**Example use cases:** Run multiple actions such as answering a call and opening a browser to show more information about the caller.

```json
{
    "@": "functionSequence",
    "sequence": [
        { "id": "answerCall" },
        { "id": "openBrowser" }
    ]
}
```

---

### First Function Of

Iterates through functions in order. For each, checks its condition, and if it should run, tries to execute it. Stops as soon as one function succeeds.

```
for function in functions:
    if function.condition() and function.execute():
        break
```

**Type:** `firstFunctionOf`

| Field | Type | Description |
|-------|------|-------------|
| `functions` | Array of function requests (min 2) | Candidate functions in priority order. |

**Example use cases:** Run a list of functions in priority order.
On iOS, navigation or web navigation functions may need to fall back to a notification function if the app is in the background.

```json
{
    "@": "firstFunctionOf",
    "sequence": [
        { "id": "openBrowser" },
        { "id": "showNotification" }
    ]
}
```

---

### Function Sequence Until

Executes functions in order until one function's condition fails or the function itself fails.

```
for function in functions:
    if not function.condition() or not function.execute():
        break
```

**Type:** `functionSequenceUntil`

| Field | Type | Description |
|-------|------|-------------|
| `sequence` | Array of function requests (min 2) | Functions to invoke in order. |

**Example use cases:** Use when the functions in the sequence depend on each other.

```json
{
    "@": "functionSequenceUntil",
    "sequence": [
        { "id": "verifyCredentials" },
        { "id": "makeAuthorizedRequestToServer" }
    ]
}
```

---

### Parallel Functions

Executes all nested functions concurrently.

**Type:** `parallel`

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `functions` | Array of function requests (min 2) | — | Functions to invoke in parallel. |
| `await` | `any`, `all` | `all` | `all` — completes when every function completes; if any fails, the sequence fails and pending functions are cancelled. `any` — completes when the first function succeeds; remaining functions are cancelled. If all fail, the sequence fails. |

**Example use cases:** Execute multiple independent functions in parallel.

```json
{
    "@": "parallel",
    "await": "all",
    "functions": [
        { "id": "verifyCredentials" },
        { "id": "makeAuthorizedRequestToServer" }
    ]
}
```

---

### With Call Scope

Creates a new call scope from given variables and executes a function within it.

- Supply `callId` to create a scope referring to a specific call (`groupId` is inferred automatically).
- Supply `groupId` to create a scope referring to a group.
- Any additional variables are transferred to the new scope.

**Type:** `withCallScope`

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `function` | Function request | — | The function to invoke in the new scope. |
| `callId` | String | `null` | Call ID. Supports [placeholders](scopes.md#supported-placeholders). If omitted, `groupId` must be specified. |
| `groupId` | String | `null` | Group ID. If omitted, inferred from `callId`. Supports [placeholders](scopes.md#supported-placeholders). |

**Example use cases:** When functions invoked from Smart Links need to call functions that require a call scope.

```json
{
    "@": "withCallScope",
    "function": {
        "id": "anotherFunction"
    },
    "callId": "*param[hello]*"
}
```