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
pageSize integer No 10 Number of items per page (max 500)
sort string No - Sort order: AlphabeticalAsc, LastModifiedDesc

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
}

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

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