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+pageSizeor legacy-styleskipCount+maxResultCount.In legacy mode, omitted aliases fall back to
skipCount=0andmaxResultCount=10. Because integrations responses still returncurrentPage,skipCountmust 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#
- Cache Results - Action links don't change frequently, consider caching for short periods
- Use Pagination - For tenants with many actions, use appropriate page sizes (max 100)
- Search Efficiently - Use search text to filter results when looking for specific actions
- Store Relevant IDs - Keep track of action IDs your application needs for workflows
- Handle Empty Results - Some tenants may have no action links configured
- Use Sorting - Sort alphabetically for better user experience in UI lists
Related Documentation#
- Executing Workflows - Use action IDs in workflow metadata
- Categories API - Get categories for content organization
- Authentication - API key setup and usage
- Troubleshooting - Common issues and solutions