Skip to content

Actions API#

The Actions endpoint allows you to retrieve action links from your Storyteller tenant. Action links provide interactive elements that can be used within stories and clips.

Endpoints#

Get All Actions#

GET https://integrations.usestoryteller.com/api/actions

Get Action by External ID#

GET https://integrations.usestoryteller.com/api/actions/{externalId}

Headers#

Header Required Description
x-storyteller-api-key Yes Your API key for authentication

Get All Actions#

Query Parameters#

Parameter Type Required Default Description
searchText string No - Filter actions by title
externalId string No - Filter actions by external ID
currentPage integer No 1 Page number for pagination. Ignored when skipCount or maxResultCount is supplied.
pageSize integer No 10 Number of items per page. Must be between 1 and 1000. Ignored when skipCount or maxResultCount is supplied.
skipCount integer No 0 Legacy offset-style pagination alias. Defaults to 0 when omitted while using legacy pagination.
maxResultCount integer No 10 Legacy offset-style page-size alias. Defaults to 10 when omitted while using legacy pagination. Maximum 1000.
sort string No - Sort order: AlphabeticalAsc, LastModifiedDesc

You can page this endpoint using either currentPage + pageSize or legacy-style skipCount + maxResultCount.

In legacy mode, omitted aliases fall back to skipCount=0 and maxResultCount=10. Because integrations responses still return currentPage, skipCount must land on a page boundary for the effective page size.

Response#

Success Response (200 OK)#

{
  "actions": [
    {
      "id": "action-link-external-id",
      "title": "Visit Our Website"
    },
    {
      "id": "newsletter-signup",
      "title": "Subscribe to Newsletter"
    }
  ],
  "pageSize": 10,
  "currentPage": 1,
  "totalPages": 1,
  "totalCount": 1
}

Get Action by External ID#

Path Parameters#

Parameter Type Required Description
externalId string Yes The external ID of the action

Response (200 OK)#

Returns a single action object with the same structure as shown above (without pagination fields).

Response (404 Not Found)#

{
  "status": 404,
  "type": "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.4",
  "title": "Not Found",
  "detail": "Action with externalId action-001 not found",
  "instance": ""
}

Response Fields#

Action Object#

Field Type Description
id string External ID for the action link
title string Display title of the action

Pagination Object#

Field Type Description
pageSize integer Number of items per page
currentPage integer Current page number
totalPages integer Total number of pages available
totalCount integer Exact total number of matching actions

Code Examples#

const fetch = require('node-fetch');

async function getActions(searchText = '', currentPage = 1, pageSize = 10, sort = '') {
  const params = new URLSearchParams({
    ...(searchText && { searchText }),
    currentPage: currentPage.toString(),
    pageSize: pageSize.toString(),
    ...(sort && { sort })
  });

  try {
    const response = await fetch(`https://integrations.usestoryteller.com/api/actions?${params}`, {
      method: 'GET',
      headers: {
        'x-storyteller-api-key': process.env.STORYTELLER_API_KEY
      }
    });

    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(`HTTP ${response.status}: ${errorData.detail}`);
    }

    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error fetching actions:', error);
    throw error;
  }
}

// Usage examples
async function examples() {
  // Get all actions
  const allActions = await getActions();
  console.log(`Found ${allActions.actions.length} actions`);

  // Search for specific actions
  const searchResults = await getActions('newsletter', 1, 20);
  console.log(`Found ${searchResults.actions.length} actions matching "newsletter"`);

  // Get actions sorted alphabetically
  const sortedActions = await getActions('', 1, 50, 'AlphabeticalAsc');
  console.log(`Retrieved ${sortedActions.actions.length} sorted actions`);

  // Get action IDs for workflow usage
  const actionIds = allActions.actions.map(action => action.id);
  console.log('Available action IDs:', actionIds);
}
import requests
import os
from urllib.parse import urlencode

def get_actions(search_text='', current_page=1, page_size=10, sort=''):
    url = 'https://integrations.usestoryteller.com/api/actions'
    headers = {
        'x-storyteller-api-key': os.environ.get('STORYTELLER_API_KEY')
    }

    params = {
        'currentPage': current_page,
        'pageSize': page_size
    }

    if search_text:
        params['searchText'] = search_text
    if sort:
        params['sort'] = sort

    try:
        response = requests.get(url, headers=headers, params=params)
        response.raise_for_status()

        data = response.json()
        return data
    except requests.exceptions.RequestException as e:
        print(f'Error fetching actions: {e}')
        if hasattr(e.response, 'json'):
            print(f'Error details: {e.response.json()}')
        raise

# Usage examples
try:
    # Get all actions
    all_actions = get_actions()
    print(f'Found {len(all_actions["actions"])} actions')

    # Search for specific actions
    search_results = get_actions(search_text='newsletter', page_size=20)
    print(f'Found {len(search_results["actions"])} actions matching "newsletter"')

    # Get actions sorted alphabetically
    sorted_actions = get_actions(page_size=50, sort='AlphabeticalAsc')
    print(f'Retrieved {len(sorted_actions["actions"])} sorted actions')

    # Extract action IDs for workflow usage
    action_ids = [action['id'] for action in all_actions['actions']]
    print('Available action IDs:', action_ids)

except Exception as e:
    print(f'Failed to fetch actions: {e}')
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Collections.Generic;
using Newtonsoft.Json;

public class ActionsClient
{
    private readonly HttpClient _httpClient;
    private readonly string _baseUrl = "https://integrations.usestoryteller.com";

    public ActionsClient(string apiKey)
    {
        _httpClient = new HttpClient();
        _httpClient.DefaultRequestHeaders.Add("x-storyteller-api-key", apiKey);
    }

    public async Task<ActionsResponse> GetActionsAsync(string searchText = "", int currentPage = 1, int pageSize = 10, string sort = "")
    {
        try
        {
            var queryParams = new List<string>
            {
                $"currentPage={currentPage}",
                $"pageSize={pageSize}"
            };

            if (!string.IsNullOrEmpty(searchText))
            {
                queryParams.Add($"searchText={Uri.EscapeDataString(searchText)}");
            }

            if (!string.IsNullOrEmpty(sort))
            {
                queryParams.Add($"sort={sort}");
            }

            var queryString = string.Join("&", queryParams);
            var response = await _httpClient.GetAsync($"{_baseUrl}/api/actions?{queryString}");
            response.EnsureSuccessStatusCode();

            var responseContent = await response.Content.ReadAsStringAsync();
            var actions = JsonConvert.DeserializeObject<ActionsResponse>(responseContent);

            return actions;
        }
        catch (HttpRequestException ex)
        {
            throw new Exception($"Error fetching actions: {ex.Message}", ex);
        }
    }
}

public class ActionsResponse
{
    public ActionItem[] Actions { get; set; }
    public int PageSize { get; set; }
    public int CurrentPage { get; set; }
    public int TotalPages { get; set; }
}

public class ActionItem
{
    public string Id { get; set; }
    public string Title { get; set; }
}

// Usage
var client = new ActionsClient(Environment.GetEnvironmentVariable("STORYTELLER_API_KEY"));

try
{
    // Get all actions
    var allActions = await client.GetActionsAsync();
    Console.WriteLine($"Found {allActions.Actions.Length} actions");

    // Search for specific actions
    var searchResults = await client.GetActionsAsync("newsletter", 1, 20);
    Console.WriteLine($"Found {searchResults.Actions.Length} actions matching 'newsletter'");

    // Get actions sorted alphabetically
    var sortedActions = await client.GetActionsAsync("", 1, 50, "AlphabeticalAsc");
    Console.WriteLine($"Retrieved {sortedActions.Actions.Length} sorted actions");

    // Extract action IDs for workflow usage
    var actionIds = allActions.Actions.Select(a => a.Id).ToArray();
    Console.WriteLine($"Available action IDs: {string.Join(", ", actionIds)}");
}
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}
# Get all actions (first page)
curl -X GET "https://integrations.usestoryteller.com/api/actions" \
  -H "x-storyteller-api-key: your-api-key-here"

# Search for specific actions
curl -X GET "https://integrations.usestoryteller.com/api/actions?searchText=newsletter&pageSize=20" \
  -H "x-storyteller-api-key: your-api-key-here"

# Filter by external ID
curl -X GET "https://integrations.usestoryteller.com/api/actions?externalId=action-001" \
  -H "x-storyteller-api-key: your-api-key-here"

# Get a specific action by external ID
curl -X GET "https://integrations.usestoryteller.com/api/actions/action-001" \
  -H "x-storyteller-api-key: your-api-key-here"

# Get actions sorted alphabetically
curl -X GET "https://integrations.usestoryteller.com/api/actions?sort=AlphabeticalAsc&pageSize=50" \
  -H "x-storyteller-api-key: your-api-key-here"

Usage with Workflows#

Action links can be referenced in workflow metadata when creating interactive content:

// 1. Get available actions
const actionsData = await getActions();
const availableActionIds = actionsData.actions.map(action => action.id);

// 2. Use action ID in workflow metadata
const workflowMetadata = {
  'https://example.com/video.mp4': {
    'Title': 'Interactive Video',
    'actionLinkId': availableActionIds[0] // Use first available action
  }
};

// 3. Execute workflow with action metadata
await executeWorkflow(['create-interactive-clip'], ['https://example.com/video.mp4'], workflowMetadata);

Pagination Example#

async function getAllActions() {
  let allActions = [];
  let currentPage = 1;
  let totalPages = 1;

  do {
    const response = await getActions('', currentPage, 50);
    allActions.push(...response.actions);
    totalPages = response.totalPages;
    currentPage++;
  } while (currentPage <= totalPages);

  return allActions;
}

// Usage
const allActions = await getAllActions();
console.log(`Retrieved ${allActions.length} total actions`);

Error Handling#

Common Error Responses#

{
  "status": 401,
  "type": "https://datatracker.ietf.org/doc/html/rfc7235#section-3.1",
  "title": "Unauthorized",
  "detail": "No valid API key provided",
  "instance": ""
}
{
  "status": 400,
  "type": "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1",
  "title": "Bad Request",
  "detail": "Invalid page size. Must be between 1 and 100",
  "instance": ""
}

Best Practices#

  1. Cache Results - Action links don't change frequently, consider caching for short periods
  2. Use Pagination - For tenants with many actions, use appropriate page sizes (max 100)
  3. Search Efficiently - Use search text to filter results when looking for specific actions
  4. Store Relevant IDs - Keep track of action IDs your application needs for workflows
  5. Handle Empty Results - Some tenants may have no action links configured
  6. Use Sorting - Sort alphabetically for better user experience in UI lists