> ## Documentation Index
> Fetch the complete documentation index at: https://docs.talkover.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Create/Update Action

> Create new actions or update existing actions for a voice agent

# Create/Update Action

Create new actions or update existing actions for a voice agent. Configures webhooks, call transfers, holds, and other actions that the agent can perform during conversations.

## Endpoint

```
POST /api/v1/agents/{agent_id}/actions
```

## Path parameters

<ParamField path="agent" type="string" required>
  The unique identifier of the voice agent.
</ParamField>

## Request headers

<ParamField header="Authorization" type="string" required>
  Bearer token for authentication. Format: `Bearer talq_your_environment_token_here`
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be set to `application/json`
</ParamField>

## Request body

<ParamField body="node_id" type="string" required>
  Action node ID for workflow integration
</ParamField>

<ParamField body="name" type="string" required>
  Action name (max 255 characters)
</ParamField>

<ParamField body="description" type="string" required>
  What the action does
</ParamField>

<ParamField body="type" type="string" required>
  Action type. Options: `webhook`, `transfer`, `hold`, `external`.
</ParamField>

<ParamField body="inputs" type="array" required={false}>
  Array of input parameters for the action
</ParamField>

<ParamField body="integration" type="object" required={false}>
  Integration configuration object
</ParamField>

<ParamField body="url" type="string" required={false}>
  Webhook URL (must be a valid URL — used by `webhook` actions).
</ParamField>

<ParamField body="authorization_url" type="string" required={false}>
  Authorization URL (must be a valid URL — used by `webhook` actions when the target requires a separate authorization endpoint).
</ParamField>

<ParamField body="authorization_scheme" type="string" required={false}>
  Authorization scheme used when calling `url`. Options: `none`, `bearer`, `basic`, `api_key`, `custom`. Default: `none`.
</ParamField>

<ParamField body="custom_headers" type="array" required={false}>
  Array of custom HTTP headers to send with the webhook request. Each item is `{ "key": "Header-Name", "value": "header-value" }`.
</ParamField>

<ParamField body="speak_on_send" type="string" required={false}>
  Phrase the agent will say when the webhook is triggered (before the call to `url`). Useful to keep the conversation natural while the integration runs.
</ParamField>

<ParamField body="speak_on_receive" type="string" required={false}>
  Phrase the agent will say after the webhook responds successfully. The webhook response can be referenced via template variables.
</ParamField>

<ParamField body="execution_mode" type="string" required={false}>
  Defines when the action runs. Options:

  * `during_call` (default) — webhook runs during the conversation, response is consumed by the agent
  * `post_call` — webhook runs after the call ends (only valid for `external` action type)
</ParamField>

<ParamField body="hold_duration" type="integer" required={false}>
  Hold duration in seconds (for `hold` actions).
</ParamField>

<ParamField body="transfer_to" type="string" required={false}>
  Transfer destination phone number in E.164 format (for `transfer` actions).
</ParamField>

<ParamField body="current_status" type="string" required={false}>
  Action status. Options: `active`, `inactive`. Default: `active`.
</ParamField>

## Example requests

<RequestExample>
  ```bash theme={null}
  # Request 1: Create webhook action
  curl -X POST "https://app.talkover.ai/api/v1/agents/550e8400-e29b-41d4-a716-446655440000/actions" \
    -H "Authorization: Bearer talq_your_environment_token_here" \
    -H "Content-Type: application/json" \
    -d '{
      "node_id": "action-node-456",
      "name": "Schedule Meeting",
      "description": "Schedule a meeting with the customer",
      "type": "webhook",
      "inputs": [
        {
          "name": "date",
          "type": "string",
          "required": true,
          "description": "Meeting date"
        },
        {
          "name": "time",
          "type": "string",
          "required": true,
          "description": "Meeting time"
        }
      ],
      "integration": {
        "id": "integration-uuid"
      },
      "url": "https://api.example.com/schedule",
      "authorization_url": "https://api.example.com/auth",
      "current_status": "active"
    }'
  ```

  ```javascript theme={null}
  // Request 1: Create webhook action
  const response = await fetch('https://app.talkover.ai/api/v1/agents/550e8400-e29b-41d4-a716-446655440000/actions', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer talq_your_environment_token_here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      node_id: "action-node-456",
      name: "Schedule Meeting",
      description: "Schedule a meeting with the customer",
      type: "webhook",
      inputs: [
        {
          name: "date",
          type: "string",
          required: true,
          description: "Meeting date"
        },
        {
          name: "time",
          type: "string",
          required: true,
          description: "Meeting time"
        }
      ],
      integration: {
        id: "integration-uuid"
      },
      url: "https://api.example.com/schedule",
      authorization_url: "https://api.example.com/auth",
      current_status: "active"
    })
  });

  const result = await response.json();
  console.log(result);
  ```
</RequestExample>

<RequestExample>
  ```bash theme={null}
  # Request 2: Create transfer action
  curl -X POST "https://app.talkover.ai/api/v1/agents/550e8400-e29b-41d4-a716-446655440000/actions" \
    -H "Authorization: Bearer talq_your_environment_token_here" \
    -H "Content-Type: application/json" \
    -d '{
      "node_id": "action-node-789",
      "name": "Transfer Call",
      "description": "Transfer the call to a human agent",
      "type": "transfer",
      "inputs": [
        {
          "name": "transfer_to",
          "type": "string",
          "required": true,
          "description": "Transfer to",
          "value": "+1234567890"
        }
      ],
      "transfer_to": "+1234567890",
      "current_status": "active"
    }'
  ```

  ```javascript theme={null}
  // Request 2: Create transfer action
  const response = await fetch('https://app.talkover.ai/api/v1/agents/550e8400-e29b-41d4-a716-446655440000/actions', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer talq_your_environment_token_here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      node_id: "action-node-789",
      name: "Transfer Call",
      description: "Transfer the call to a human agent",
      type: "transfer",
      inputs: [
        {
          name: "transfer_to",
          type: "string",
          required: true,
          description: "Transfer to",
          value: "+1234567890"
        }
      ],
      transfer_to: "+1234567890",
      current_status: "active"
    })
  });

  const result = await response.json();
  console.log(result);
  ```
</RequestExample>

<RequestExample>
  ```bash theme={null}
  # Request 3: Create hold action
  curl -X POST "https://app.talkover.ai/api/v1/agents/550e8400-e29b-41d4-a716-446655440000/actions" \
    -H "Authorization: Bearer talq_your_environment_token_here" \
    -H "Content-Type: application/json" \
    -d '{
      "node_id": "action-node-101",
      "name": "Put Call on Hold",
      "description": "Put the current call on hold for a specified duration",
      "type": "hold",
      "inputs": [
        {
          "name": "hold_duration",
          "type": "integer",
          "required": true,
          "description": "Hold duration in seconds",
          "value": 30
        }
      ],
      "hold_duration": 30,
      "current_status": "active"
    }'
  ```

  ```javascript theme={null}
  // Request 3: Create hold action
  const response = await fetch('https://app.talkover.ai/api/v1/agents/550e8400-e29b-41d4-a716-446655440000/actions', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer talq_your_environment_token_here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      node_id: "action-node-101",
      name: "Put Call on Hold",
      description: "Put the current call on hold for a specified duration",
      type: "hold",
      inputs: [
        {
          name: "hold_duration",
          type: "integer",
          required: true,
          description: "Hold duration in seconds",
          value: 30
        }
      ],
      hold_duration: 30,
      current_status: "active"
    })
  });

  const result = await response.json();
  console.log(result);
  ```
</RequestExample>

## Response

### Success Response (200 OK)

<ResponseExample>
  ```json theme={null}
  {
    "success": true,
    "message": "Agent action updated successfully",
    "data": {
      "id": "action-uuid-1",
      "name": "Schedule Meeting",
      "label": "Schedule Meeting",
      "description": "Schedule a meeting with the customer",
      "type": "webhook",
      "input_schema": [
        {
          "name": "date",
          "type": "string",
          "required": true,
          "description": "Meeting date"
        },
        {
          "name": "time",
          "type": "string",
          "required": true,
          "description": "Meeting time"
        }
      ],
      "config": null,
      "action_trigger": null,
      "url": "https://api.example.com/schedule",
      "authorization_url": "https://api.example.com/auth",
      "current_status": "active",
      "created_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-01-15T12:30:00Z"
    }
  }
  ```
</ResponseExample>

### Response fields

<ResponseField name="success" type="boolean" required>
  Indicates if the operation was successful.
</ResponseField>

<ResponseField name="message" type="string" required>
  Success message confirming the action was created or updated.
</ResponseField>

<ResponseField name="data" type="object" required>
  The created or updated action object.

  <Expandable title="Action Object">
    <ResponseField name="id" type="string" required>
      Unique identifier for the action.
    </ResponseField>

    <ResponseField name="name" type="string" required>
      The name of the action.
    </ResponseField>

    <ResponseField name="label" type="string" required>
      Display label for the action.
    </ResponseField>

    <ResponseField name="description" type="string" required>
      What the action does.
    </ResponseField>

    <ResponseField name="type" type="string" required>
      Type of action. Options: `webhook`, `transfer`, `hold`, `external`.
    </ResponseField>

    <ResponseField name="input_schema" type="array" required>
      Array of input parameters required for the action.
    </ResponseField>

    <ResponseField name="config" type="object">
      Configuration object for the action (if applicable).
    </ResponseField>

    <ResponseField name="action_trigger" type="object">
      Trigger conditions for the action (if applicable).
    </ResponseField>

    <ResponseField name="url" type="string">
      Webhook URL for webhook-type actions.
    </ResponseField>

    <ResponseField name="authorization_url" type="string">
      Authorization URL for webhook-type actions.
    </ResponseField>

    <ResponseField name="current_status" type="string" required>
      Current status of the action. Options: `active`, `inactive`.
    </ResponseField>

    <ResponseField name="created_at" type="string" required>
      ISO 8601 timestamp when the action was created.
    </ResponseField>

    <ResponseField name="updated_at" type="string" required>
      ISO 8601 timestamp when the action was last updated.
    </ResponseField>
  </Expandable>
</ResponseField>

## Error responses

### Validation Error (422)

<ResponseExample>
  ```json theme={null}
  {
    "success": false,
    "message": "The given data was invalid.",
    "errors": {
      "name": [
        "The name field is required."
      ],
      "type": [
        "The selected type is invalid."
      ],
      "url": [
        "The url must be a valid URL."
      ],
      "authorization_url": [
        "The authorization url must be a valid URL."
      ]
    }
  }
  ```
</ResponseExample>

### 404 Not Found

<ResponseExample>
  ```json theme={null}
  {
    "success": false,
    "message": "Agent not found"
  }
  ```
</ResponseExample>

### 401 Unauthorized

<ResponseExample>
  ```json theme={null}
  {
    "success": false,
    "message": "Unauthenticated."
  }
  ```
</ResponseExample>

### 403 Forbidden

<ResponseExample>
  ```json theme={null}
  {
    "success": false,
    "message": "You are not authorized to create actions for this agent."
  }
  ```
</ResponseExample>

### 500 Server Error

<ResponseExample>
  ```json theme={null}
  {
    "success": false,
    "message": "Internal server error."
  }
  ```
</ResponseExample>

## Error codes

| Code               | Description                                                    | HTTP Status |
| ------------------ | -------------------------------------------------------------- | ----------- |
| `AGENT_NOT_FOUND`  | Specified agent does not exist                                 | 404         |
| `INVALID_TOKEN`    | Authentication token is invalid or missing                     | 401         |
| `UNAUTHORIZED`     | User does not have permission to create actions for this agent | 403         |
| `VALIDATION_ERROR` | Request data validation failed                                 | 422         |
| `SERVER_ERROR`     | Internal server error occurred                                 | 500         |

## Important notes

<Info>
  **Agent status will be set to draft.** After creating or updating actions, the agent will be automatically set to "draft" status and will need to be published again to become active.
</Info>

<Info>
  **Action types have different requirements.** Different action types (webhook, transfer, hold) require different parameters and configurations.
</Info>

<Warning>
  **URL validation.** For webhook actions, both `url` and `authorization_url` must be valid URLs.
</Warning>

## Related endpoints

* **List Actions**: `GET /api/v1/agents/{agent_id}/actions`
* **Delete Action**: `DELETE /api/v1/agents/{agent_id}/actions/{action_id}`
* **Get Agent**: `GET /api/v1/agents/{agent_id}`
* **Publish Agent**: `POST /api/v1/agents/{agent_id}/publish`
