StoryCADApi Class
The main entry point for StoryCADLib API operations.
namespace StoryCADLib.Services.API
public class StoryCADApi : IStoryCADAPI
# In Python, the API is the StoryCAD object itself.
from storycad import StoryCAD
Overview
StoryCADApi provides methods for creating, reading, updating, and deleting story elements. All methods are decorated with [KernelFunction] for Semantic Kernel integration, but can also be called directly.
Key Concepts:
- All methods return
OperationResult<T>- checkIsSuccessbefore usingPayload - The API maintains a
CurrentModelproperty holding the active story - Set
CurrentModelviaCreateEmptyOutline()orOpenOutline()before other operations
Getting an Instance
using StoryCADLib.Services.IoC;
using StoryCADLib.Services.API;
using CommunityToolkit.Mvvm.DependencyInjection;
// Initialize (once at startup)
BootStrapper.Initialise(headless: true);
// Get the API instance
var api = Ioc.Default.GetRequiredService<StoryCADApi>();
from storycad import StoryCAD
# Initialize (once at startup): the sc object is the API instance
sc = StoryCAD(headless=True)
Outline Operations
CreateEmptyOutline
Creates a new empty story outline based on a template.
public async Task<OperationResult<List<Guid>>> CreateEmptyOutline(
string name,
string author,
string templateIndex)
def create_empty_outline(title, author, template_index="0"):
... # returns a list of element handles; [0] is the Story Overview
Parameters:
| Name | Type | Description |
|——|——|————-|
| name | string | Title of the story |
| author | string | Author name |
| templateIndex | string | Starter template as a string, "0" to "5": "0" Blank, "1" Overview + Story Problem, "2" Folders, "3" External + Internal Problems, "4" Protagonist + Antagonist, "5" Problems + Characters |
Returns: OperationResult<List<Guid>> - GUIDs of created elements
Example:
var result = await api.CreateEmptyOutline("My Story", "Jane Doe", "0");
if (result.IsSuccess)
{
Console.WriteLine($"Created {result.Payload.Count} elements");
}
elements = sc.create_empty_outline("My Story", "Jane Doe", template_index="0")
print(f"Created {len(elements)} elements")
OpenOutline
Opens an existing story outline from disk.
public async Task<OperationResult<bool>> OpenOutline(string path)
def open_outline(path):
...
Parameters:
| Name | Type | Description |
|——|——|————-|
| path | string | Full path to the .stbx file |
Returns: OperationResult<bool> - true on success
Example:
var result = await api.OpenOutline("C:/Stories/my-story.stbx");
if (result.IsSuccess)
{
var elements = api.GetAllElements();
}
sc.open_outline("C:/Stories/my-story.stbx")
elements = sc.get_all_elements()
WriteOutline
Saves the current outline to disk.
public async Task<OperationResult<string>> WriteOutline(string filePath)
def write_outline(path):
...
Parameters:
| Name | Type | Description |
|——|——|————-|
| filePath | string | Full path for the .stbx file |
Returns: OperationResult<string> - Success message
Example:
var result = await api.WriteOutline("C:/Stories/my-story.stbx");
if (!result.IsSuccess)
{
Console.WriteLine($"Save failed: {result.ErrorMessage}");
}
try:
sc.write_outline("C:/Stories/my-story.stbx")
except Exception as error:
print(f"Save failed: {error}") # the wrapper raises instead of returning a result
Element Operations
GetAllElements
Returns all elements in the current model.
public OperationResult<ObservableCollection<StoryElement>> GetAllElements()
def get_all_elements():
... # iterable of element handles
Returns: OperationResult<ObservableCollection<StoryElement>> - All story elements
GetElementsByType
Gets all elements of a specific type.
public OperationResult<List<StoryElement>> GetElementsByType(StoryItemType elementType)
def get_elements_by_type(item_type):
... # iterable of element handles
Parameters:
| Name | Type | Description |
|——|——|————-|
| elementType | StoryItemType | The type to filter by |
Valid Types: Problem, Character, Setting, Scene, Folder, Section, Web, Notes, StoryWorld. StoryOverview is also accepted and returns the singleton overview element.
Example:
var result = api.GetElementsByType(StoryItemType.Character);
if (result.IsSuccess)
{
foreach (var character in result.Payload)
{
Console.WriteLine(character.Name);
}
}
for character in sc.get_elements_by_type(sc.item_type.Character):
print(character.name)
GetStoryElement
Gets a specific element by its GUID.
public OperationResult<StoryElement> GetStoryElement(Guid guid)
def get_element(element):
... # returns the element's full state as a JSON string
Parameters:
| Name | Type | Description |
|——|——|————-|
| guid | Guid | The element’s unique identifier |
Returns: OperationResult<StoryElement> - The requested element
AddElement
Creates a new story element.
public OperationResult<Guid> AddElement(
StoryItemType typeToAdd,
string parentGUID,
string name,
string description = "")
def add_element(item_type, parent, name):
... # returns an element handle
Parameters:
| Name | Type | Description |
|——|——|————-|
| typeToAdd | StoryItemType | Type of element to create |
| parentGUID | string | GUID of parent element (as string) |
| name | string | Name for the new element |
| description | string | Optional description |
Returns: OperationResult<Guid> - GUID of created element
Example:
// Get the story overview (root) GUID
var overview = api.GetElementsByType(StoryItemType.StoryOverview);
var rootGuid = overview.Payload.First().Uuid.ToString();
// Add a character
var result = api.AddElement(
StoryItemType.Character,
rootGuid,
"Alex",
"The protagonist");
if (result.IsSuccess)
{
Console.WriteLine($"Created character with GUID: {result.Payload}");
}
# Get the story overview (root)
overview = next(iter(sc.get_elements_by_type(sc.item_type.StoryOverview)))
# Add a character
character = sc.add_element(sc.item_type.Character, overview, "Alex")
print(f"Created character with GUID: {character.uuid}")
AddElementWithProperties
Creates a new story element with initial properties and an optional GUID override.
Semantic Kernel name: This method is registered as
AddElementWithPropertiesvia[KernelFunction("AddElementWithProperties")]to distinguish it from the basicAddElementoverload in SK plugin registration.
public OperationResult<Guid> AddElement(
StoryItemType typeToAdd,
string parentGUID,
string name,
Dictionary<string, object> properties,
string GUIDOverride = "")
# Add the element, then set its initial properties.
element = sc.add_element(item_type, parent, name)
sc.update_element_properties(element, {"Role": "Protagonist"})
Parameters:
| Name | Type | Description |
|——|——|————-|
| typeToAdd | StoryItemType | Type of element to create |
| parentGUID | string | GUID of parent element (as string) |
| name | string | Name for the new element |
| properties | Dictionary | Initial property values to set |
| GUIDOverride | string | Optional: specify a GUID for the new element (must be unique) |
Returns: OperationResult<Guid> - GUID of created element
Example:
var props = new Dictionary<string, object>
{
{ "Role", "Protagonist" },
{ "Age", "28" },
{ "Archetype", "The Hero" }
};
var result = api.AddElement(
StoryItemType.Character,
rootGuid,
"Elena",
props);
elena = sc.add_element(sc.item_type.Character, overview, "Elena")
sc.update_element_properties(
elena,
{"Role": "Protagonist", "Age": "28", "Archetype": "The Hero"},
)
UpdateElementProperty
Updates a single property on an element.
public OperationResult<StoryElement> UpdateElementProperty(
Guid elementUuid,
string propertyName,
object value)
def update_element_property(element, property_name, value):
...
Parameters:
| Name | Type | Description |
|——|——|————-|
| elementUuid | Guid | The element’s GUID |
| propertyName | string | Name of the property to update |
| value | object | New value for the property |
Returns: OperationResult<StoryElement> - Updated element
Example:
var result = api.UpdateElementProperty(
characterGuid,
"Role",
"Protagonist");
sc.update_element_property(character, "Role", "Protagonist")
UpdateElementProperties
Updates multiple properties on an element.
public OperationResult<bool> UpdateElementProperties(
Guid elementGuid,
Dictionary<string, object> properties)
def update_element_properties(element, properties):
...
Parameters:
| Name | Type | Description |
|——|——|————-|
| elementGuid | Guid | The element’s GUID |
| properties | Dictionary | Property names and values |
Example:
var props = new Dictionary<string, object>
{
{ "Name", "Alex" },
{ "Role", "Protagonist" },
{ "Age", "32" }
};
api.UpdateElementProperties(characterGuid, props);
sc.update_element_properties(
character,
{"Name": "Alex", "Role": "Protagonist", "Age": "32"},
)
DeleteElement
Moves an element to the trash.
public Task<OperationResult<bool>> DeleteElement(Guid elementToDelete)
def delete_element(element):
...
Parameters:
| Name | Type | Description |
|——|——|————-|
| elementToDelete | Guid | The element’s GUID |
Returns: OperationResult<bool> - true on success
GetElement
Returns a single element with all its fields as a serialized object. Unlike GetStoryElement which returns a typed StoryElement, this returns the full serialized representation including all fields.
public OperationResult<object> GetElement(Guid guid)
def get_element(element):
... # returns the full serialized element as a JSON string
Parameters:
| Name | Type | Description |
|——|——|————-|
| guid | Guid | The element’s unique identifier |
Returns: OperationResult<object> - Serialized element with all fields
Example:
var result = api.GetElement(characterGuid);
if (result.IsSuccess)
{
Console.WriteLine(result.Payload); // Full serialized element
}
import json
detail = json.loads(sc.get_element(character))
print(detail) # Full serialized element
UpdateStoryElement
Replaces an entire story element by deserializing a new element and updating it in the model. For updating individual properties, prefer UpdateElementProperty or UpdateElementProperties.
public OperationResult<bool> UpdateStoryElement(object newElement, Guid guid)
# Prefer update_element_property / update_element_properties for individual fields.
sc.update_element_properties(element, {"Name": "Alex"})
Parameters:
| Name | Type | Description |
|——|——|————-|
| newElement | object | Serialized element data (will be deserialized via StoryElement.Deserialize) |
| guid | Guid | The GUID of the element to replace |
Returns: OperationResult<bool> - true on success
MoveElement
Moves an element to a new parent in the outline’s ExplorerView tree. Validates against circular references, moving the root element, and moving the TrashCan.
public OperationResult<bool> MoveElement(Guid elementGuid, Guid newParentGuid)
def move_element(element, new_parent, index=None):
...
Parameters:
| Name | Type | Description |
|——|——|————-|
| elementGuid | Guid | GUID of the element to move |
| newParentGuid | Guid | GUID of the new parent element |
Returns: OperationResult<bool> - true on success
Validation:
- Cannot move an element to itself
- Cannot move the root element
- Cannot move the TrashCan
- Cannot move an element to one of its own descendants (circular reference check)
Example:
// Move a scene under a different folder
var result = api.MoveElement(sceneGuid, newFolderGuid);
if (result.IsSuccess)
{
Console.WriteLine("Element moved successfully");
await api.WriteOutline("my-story.stbx"); // Save changes
}
# Move a scene under a different folder
sc.move_element(scene, new_folder)
print("Element moved successfully")
sc.write_outline("my-story.stbx") # Save changes
Search Operations
SearchForText
Searches for text across all elements.
public OperationResult<List<Dictionary<string, object>>> SearchForText(string searchText)
def search_for_text(text):
...
Returns: List of dictionaries containing matching elements and properties.
SearchForReferences
Finds elements that reference a target element.
public OperationResult<List<Dictionary<string, object>>> SearchForReferences(Guid targetUuid)
def search_for_references(element):
...
SearchInSubtree
Searches within a subtree of the outline.
public OperationResult<List<Dictionary<string, object>>> SearchInSubtree(
Guid rootNodeGuid,
string searchText)
def search_in_subtree(element, text):
...
RemoveReferences
Removes all references to a target element from other elements in the outline.
public OperationResult<int> RemoveReferences(Guid targetUuid)
def remove_references(element):
... # returns the number of references removed
Parameters:
| Name | Type | Description |
|——|——|————-|
| targetUuid | Guid | GUID of the element whose references should be removed |
Returns: OperationResult<int> - Number of references removed
Relationship Operations
AddCastMember
Adds a character to a scene’s cast.
public OperationResult<bool> AddCastMember(Guid scene, Guid character)
def add_cast_member(scene, character):
...
AddRelationship
Creates a relationship between two characters.
public OperationResult<bool> AddRelationship(
Guid source,
Guid recipient,
string desc,
bool mirror = false)
def add_relationship(a, b, desc, mirror=False):
...
Parameters:
| Name | Type | Description |
|——|——|————-|
| source | Guid | First character’s GUID |
| recipient | Guid | Second character’s GUID |
| desc | string | Description of relationship |
| mirror | bool | If true, creates reciprocal relationship |
Trash Operations
RestoreFromTrash
Restores a deleted element from the trash.
public Task<OperationResult<bool>> RestoreFromTrash(Guid elementToRestore)
def restore_from_trash(element):
...
EmptyTrash
Permanently deletes all trashed elements.
public Task<OperationResult<bool>> EmptyTrash()
def empty_trash():
...
Resource Data Methods
These methods provide access to StoryCAD’s built-in reference data.
GetExamples
Gets example values for a property.
public OperationResult<IEnumerable<string>> GetExamples(string propertyName)
def get_examples(property_name):
...
GetConflictCategories
Gets available conflict type categories.
public OperationResult<IEnumerable<string>> GetConflictCategories()
def get_conflict_categories():
...
GetKeyQuestionElements
Gets key question prompts for story development.
public OperationResult<IEnumerable<string>> GetKeyQuestionElements()
def get_key_question_elements():
...
Internal / Advanced Methods
These methods are used internally by StoryCAD and the Collaborator plugin. They are available in the public API but most consumers should use the standard methods above.
SetCurrentModel
Sets the active StoryModel. Used by the Collaborator plugin to synchronize the API with StoryCAD’s active outline.
public void SetCurrentModel(StoryModel model)
# (no direct Python equivalent: this is a .NET Collaborator-plugin
# synchronization hook used internally by StoryCAD)
Parameters:
| Name | Type | Description |
|——|——|————-|
| model | StoryModel | The active StoryModel from ShellViewModel |
Note: This is one of the few API methods that does not return
OperationResult<T>.
DeleteStoryElement
Moves an element to the trash. This is an older variant that accepts a string GUID. Prefer DeleteElement(Guid) for new code.
public OperationResult<bool> DeleteStoryElement(string uuid)
# Older string-GUID variant; prefer delete_element(element) for new code.
def delete_element(element):
...
Parameters:
| Name | Type | Description |
|——|——|————-|
| uuid | string | The element’s GUID as a string |
Returns: OperationResult<bool> - true on success