API Reference
Complete REST API documentation for Archivist. All endpoints require the x-api-key header unless noted.
New to Archivist? Start with Core Concepts and the Data Models.
Supported Methods
Quick reference for HTTP methods supported by each resource.
| Resource | GET | POST | PUT | PATCH | DELETE |
|---|---|---|---|---|---|
| Campaigns | ✓ | ✓ | — | ✓ | ✓ |
| Characters | ✓ | ✓ | — | ✓ | ✓ |
| Sessions | ✓ | — | — | ✓ | — |
| Beats | ✓ | ✓ | — | ✓ | ✓ |
| Moments | ✓ | ✓ | — | ✓ | ✓ |
| Factions | ✓ | ✓ | — | ✓ | ✓ |
| Locations | ✓ | ✓ | — | ✓ | ✓ |
| Items | ✓ | ✓ | — | ✓ | ✓ |
| Journal Entries | ✓ | ✓ | ✓ | — | ✓ |
| Journal Folders | ✓ | ✓ | ✓ | — | ✓ |
| Links | ✓ | ✓ | — | ✓ | ✓ |
| Ask (RAG) | — | ✓ | — | — | — |
Health
/healthHealth check for the API service (no auth required).
Request Example
curl https://api.myarchivist.ai/healthResponses
{
"status": "healthy",
"service": "archivist-api",
"version": "1.0.0",
"environment": "production",
"port": 8000,
"timestamp": "2025-01-15T10:30:00.123456Z"
}Ask (RAG)
/v1/askRAG chat endpoint for campaign questions. Supports chat history and streaming.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
campaign_id*— ID of your campaignmessages*— Chat messages: [{ role, content }]stream— Return a streaming responsegm_permissions— When true, grant full journal access for the request (overrides asker_id). Defaults to false.asker_id— Optional user ID to scope journal access; must be a player/admin/owner of the campaign. Defaults to null.Request Example
curl -X POST \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"campaign_id": "your-campaign-id",
"messages": [ {"role": "user", "content": "Who is Cassius Traven?"} ],
"gm_permissions": false,
"asker_id": null
}' \
https://api.myarchivist.ai/v1/askResponses
{
"answer": "Cassius Traven is a shadowy information broker who operates in the city's underground...",
"monthlyTokensRemaining": 12345,
"hourlyTokensRemaining": 6789
}{
"detail": "messages is required"
}{
"detail": "Invalid API key"
}{
"detail": "asker_id user does not have access to this world"
}{
"detail": "asker_id user not found"
}{
"detail": "Monthly token limit exceeded"
}Campaigns
/v1/campaignsList your campaigns.
Headers
x-api-key*— Your API keyQuery Params
page— Page numbersize— Page sizeRequest Example
curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/campaigns?page=1&size=10"Responses
{
"data": [
{
"id": "camp_abc123",
"title": "Shadows of Elyndor",
"description": "A dark fantasy campaign",
"system": "D&D 5e",
"public": false,
"created_at": "2024-01-15T10:30:00Z"
}
],
"total": 1,
"page": 1,
"size": 20,
"pages": 1
}{
"detail": "Invalid API key"
}/v1/campaigns/{campaign_id}Get a specific campaign by ID.
Headers
x-api-key*— Your API keyRequest Example
curl -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/campaigns/abc123Responses
{
"id": "camp_abc123",
"title": "Shadows of Elyndor",
"description": "A dark fantasy campaign",
"system": "D&D 5e",
"public": false,
"created_at": "2024-01-15T10:30:00Z"
}{
"detail": "Campaign not found"
}{
"detail": "Invalid API key"
}/v1/campaignsCreate a new campaign. Creation bootstraps the same baseline records as the Archivist web app: the owner is added as a player/admin, a default GM speaker is created, Character Arc defaults are seeded, and default compendium field definitions are created.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
title*— Campaign titledescription— Campaign descriptionsystem— Game system (e.g. D&D 5e)Request Example
curl -X POST \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "My Epic Campaign",
"description": "A thrilling adventure",
"system": "D&D 5e"
}' \
https://api.myarchivist.ai/v1/campaignsResponses
{
"id": "camp_new123",
"title": "My Epic Campaign",
"description": "A thrilling adventure",
"system": "D&D 5e",
"public": false,
"created_at": "2024-01-25T16:45:00Z"
}{
"detail": "title is required"
}{
"detail": "Invalid API key"
}/v1/campaigns/{campaign_id}Update a campaign.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
title— Campaign titledescription— Campaign descriptionRequest Example
curl -X PATCH \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title": "Updated Campaign Name"}' \
https://api.myarchivist.ai/v1/campaigns/abc123Responses
{
"id": "camp_abc123",
"title": "Updated Campaign Name",
"description": "A dark fantasy campaign",
"system": "D&D 5e",
"public": false,
"created_at": "2024-01-15T10:30:00Z"
}{
"detail": "Campaign not found"
}{
"detail": "Invalid API key"
}/v1/campaigns/{campaign_id}Permanently delete a campaign. This action cannot be undone.
Headers
x-api-key*— Your API keyRequest Example
curl -X DELETE -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/campaigns/abc123Responses
(no content){
"detail": "Campaign not found"
}{
"detail": "Invalid API key"
}/v1/campaigns/{campaign_id}/statsGet campaign statistics (character count, session count, etc).
Headers
x-api-key*— Your API keyRequest Example
curl -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/campaigns/abc123/statsResponses
{
"campaignId": "camp_abc123",
"characters": 12,
"sessions": 24,
"moments": 156,
"beats": 48,
"factions": 5,
"locations": 18,
"items": 32
}{
"detail": "Campaign not found"
}/v1/campaigns/{campaign_id}/linksList links between entities in a campaign. Supports filtering by source/target entities and alias.
Headers
x-api-key*— Your API keyQuery Params
page— Page numbersize— Page sizefrom_id— Filter by source entity IDfrom_type— Filter by source entity type (Character, Location, etc.)to_id— Filter by target entity IDto_type— Filter by target entity typealias— Filter by relationship label/aliasRequest Example
curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/campaigns/abc123/links?from_id=char_456&from_type=Character"Responses
{
"data": [
{
"id": "link_123",
"campaign_id": "camp_abc123",
"from_id": "char_456",
"from_type": "Character",
"to_id": "char_789",
"to_type": "Character",
"alias": "friends",
"created_at": "2024-01-15T10:30:00Z"
}
],
"total": 25,
"page": 1,
"size": 20,
"pages": 2
}/v1/campaigns/{campaign_id}/linksCreate or update a link between two entities. Source and target records must both exist in the same campaign, and aliases are normalized/deduped server-side.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
from_id*— Source entity IDfrom_type*— Source entity type (Character, Location, etc)to_id*— Target entity IDto_type*— Target entity typealias— Relationship labelResponses
{
"id": "link_new123",
"campaign_id": "camp_abc123",
"from_id": "char_456",
"from_type": "Character",
"to_id": "loc_789",
"to_type": "Location",
"alias": "home",
"created_at": "2024-01-25T16:45:00Z"
}{
"detail": "Target Character not found"
}{
"detail": "Link source and target must belong to the same world"
}/v1/campaigns/{campaign_id}/links/{link_id}Update a link alias. Aliases are normalized with the same rules used during create.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
alias— Updated relationship labelResponses
{
"id": "link_123",
"campaign_id": "camp_abc123",
"from_id": "char_456",
"from_type": "Character",
"to_id": "loc_789",
"to_type": "Location",
"alias": "updated label",
"created_at": "2024-01-15T10:30:00Z"
}{
"detail": "Link not found"
}{
"detail": "Link alias cannot be empty"
}/v1/campaigns/{campaign_id}/links/{link_id}Delete a link.
Headers
x-api-key*— Your API keyResponses
(no content){
"detail": "Link not found"
}Worlds
/v1/worldsCreate a new world directly. This uses the same bootstrap flow as POST /v1/campaigns: owner player/admin membership, default GM speaker, Character Arc seed data, and default compendium field definitions are created automatically.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
title*— World titledescription— World descriptionsystem— Game system (e.g. D&D 5e)public— Whether the world is publicly visibleRequest Example
curl -X POST \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "The Hollow Marches",
"description": "Frontier ruins and old gods",
"system": "Shadowdark",
"public": false
}' \
https://api.myarchivist.ai/v1/worldsResponses
{
"id": "world_new123",
"title": "The Hollow Marches",
"description": "Frontier ruins and old gods",
"system": "Shadowdark",
"public": false,
"created_at": "2024-01-25T16:45:00Z"
}{
"detail": "Campaign limit reached for tier 'free' (1 max active campaigns)"
}Characters
/v1/charactersList characters filtered by campaign. The legacy `player_name` field is deprecated; responses may include a nullable read-only `player` object sourced from Speaker.
Headers
x-api-key*— Your API keyQuery Params
campaign_id*— Campaign IDsearch— Search by namecharacter_type— PC, NPC, etc.approved_only— Filter approved (default true)with_links— Preserve wikilink markupRequest Example
curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/characters?campaign_id=abc123"Responses
{
"data": [
{
"id": "char_123",
"campaign_id": "camp_abc123",
"character_name": "Thorin Ironforge",
"player_name": null,
"player": {
"id": "speaker_123",
"name": "John Smith",
"handle": "johnsmith",
"roles": ["Player"],
"campaign_id": "camp_abc123",
"created_at": "2024-01-10T08:00:00Z"
},
"description": "A brave dwarf warrior",
"type": "PC",
"approved": true,
"created_at": "2024-01-15T10:30:00Z"
}
],
"total": 1,
"page": 1,
"size": 20,
"pages": 1
}{
"detail": "campaign_id is required"
}{
"detail": "Invalid API key"
}/v1/characters/{character_id}Get a specific character by ID. The response may include aliases, backstory, speaker linkage, and a nullable read-only `player` object; `player_name` remains legacy.
Headers
x-api-key*— Your API keyQuery Params
with_links— Preserve wikilink markupRequest Example
curl -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/characters/char-123Responses
{
"id": "char_123",
"campaign_id": "camp_abc123",
"character_name": "Thorin Ironforge",
"character_aliases": ["Thorin", "Ironforge"],
"player_name": null,
"player": {
"id": "speaker_123",
"name": "John Smith",
"handle": "johnsmith",
"roles": ["Player"],
"campaign_id": "camp_abc123",
"created_at": "2024-01-10T08:00:00Z"
},
"description": "A brave dwarf warrior",
"backstory": "Raised in the halls beneath Emberpeak...",
"speaker_id": "speaker_123",
"type": "PC",
"approved": true,
"created_at": "2024-01-15T10:30:00Z"
}{
"detail": "Character not found"
}/v1/charactersCreate a new character. `player` is response-only and is not accepted in the request body. Additive parity fields include `character_aliases`/`characterAliases`, `speaker_id`/`speakerId`, and `backstory`; legacy `character_alias` and `player_name` are still accepted.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
character_name*— Character namecampaign_id*— Campaign IDcharacter_alias— Deprecated single alias field; merged into character_aliases after sanitizationcharacter_aliases— Array of aliases (camelCase `characterAliases` also accepted)player_name— Deprecated legacy player name fieldspeaker_id— Linked Speaker ID in the same campaign (camelCase `speakerId` also accepted)description— Character descriptionbackstory— Character backstory; wikilinks are resolved and stored separately from description linkstype— PC, NPC, etc.image— HTTPS image URL (max 2048 chars)Request Example
curl -X POST \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"character_name": "Thorin Ironforge",
"character_aliases": ["Thorin", "Ironforge"],
"description": "A brave dwarf warrior",
"backstory": "Raised in the halls beneath Emberpeak...",
"speaker_id": "speaker_123",
"type": "PC",
"campaign_id": "abc123"
}' \
https://api.myarchivist.ai/v1/charactersResponses
{
"id": "char_new456",
"campaign_id": "camp_abc123",
"character_name": "Thorin Ironforge",
"character_aliases": ["Thorin", "Ironforge"],
"player_name": null,
"player": null,
"description": "A brave dwarf warrior",
"backstory": "Raised in the halls beneath Emberpeak...",
"speaker_id": "speaker_123",
"type": "PC",
"approved": false,
"created_at": "2024-01-25T16:45:00Z"
}{
"detail": "speaker_id must belong to the same world"
}{
"detail": "image must be an HTTPS URL"
}{
"detail": "Campaign not found"
}/v1/characters/{character_id}Update a character. `player` is response-only and is not accepted in the request body. PATCH supports the same additive parity fields as POST.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
character_name— Character namecharacter_alias— Deprecated single alias fieldcharacter_aliases— Alias list (camelCase `characterAliases` also accepted)player_name— Deprecated legacy player name fieldspeaker_id— Linked Speaker ID (camelCase `speakerId` also accepted)description— Character descriptionbackstory— Character backstorytype— PC, NPC, etc.image— HTTPS image URL (max 2048 chars)Responses
{
"id": "char_123",
"campaign_id": "camp_abc123",
"character_name": "Thorin Ironforge the Bold",
"character_aliases": ["Thorin", "The Bold"],
"player_name": null,
"player": {
"id": "speaker_123",
"name": "John Smith",
"handle": "johnsmith",
"roles": ["Player"],
"campaign_id": "camp_abc123",
"created_at": "2024-01-10T08:00:00Z"
},
"description": "A brave dwarf warrior with a legendary magic axe",
"backstory": "Raised in the halls beneath Emberpeak and sworn to the old kings...",
"speaker_id": "speaker_123",
"type": "PC",
"approved": true,
"created_at": "2024-01-15T10:30:00Z"
}{
"detail": "Character name cannot match the linked speaker name"
}{
"detail": "Character not found"
}/v1/characters/{character_id}Delete a character.
Headers
x-api-key*— Your API keyResponses
(no content){
"detail": "Character not found"
}Sessions
/v1/sessionsList sessions in a campaign.
Headers
x-api-key*— Your API keyQuery Params
campaign_id*— Campaign IDsession_type— audioUpload, playByPost, discordVoice, etc.public_only— Show only public sessionswith_links— Preserve wikilink markupRequest Example
curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/sessions?campaign_id=abc123"Responses
{
"data": [
{
"id": "session_123",
"campaign_id": "camp_abc123",
"type": "audioUpload",
"title": "The Lost Mines of Phandelver",
"summary": "The party explored the ancient mines...",
"session_date": "2024-01-20T19:00:00Z",
"public": false,
"created_at": "2024-01-20T22:30:00Z"
}
],
"total": 24,
"page": 1,
"size": 20,
"pages": 2
}{
"detail": "campaign_id is required"
}/v1/sessions/{session_id}Get a specific session by ID.
Headers
x-api-key*— Your API keyQuery Params
include_beats— Include related beatsinclude_moments— Include related momentswith_links— Preserve wikilink markupRequest Example
curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/sessions/session-123?include_beats=true"Responses
{
"id": "session_123",
"campaign_id": "camp_abc123",
"type": "audioUpload",
"title": "The Lost Mines of Phandelver",
"summary": "The party explored the ancient mines...",
"session_date": "2024-01-20T19:00:00Z",
"public": false,
"created_at": "2024-01-20T22:30:00Z"
}{
"detail": "Session not found"
}/v1/sessions/{session_id}/cast-analysisGet stored cast analysis data for a session.
Headers
x-api-key*— Your API keyRequest Example
curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/sessions/session-123/cast-analysis"Responses
{
"id": "cast_analysis_123",
"session_id": "session_123",
"analysis": {
"coreSessionMetrics": {
"totalLines": 1284,
"totalWords": 18201,
"avgWordsPerLine": 14.18,
"totalTurns": 1284,
"avgTurnWords": 14.18
},
"talkShare": {
"GM": 0.42,
"Player 1": 0.31,
"Player 2": 0.27
}
},
"created_at": "2025-01-12T20:30:00Z",
"updated_at": "2025-01-12T20:30:00Z"
}{
"detail": "Cast analysis not found"
}/v1/sessions/{session_id}Update a session (title, summary, or session_date only).
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
title— Session titlesummary— Session summarysession_date— ISO datetimeResponses
{
"id": "session_123",
"campaign_id": "camp_abc123",
"type": "audioUpload",
"title": "Updated Session Title",
"summary": "Updated summary...",
"session_date": "2024-01-20T19:00:00Z",
"public": false,
"created_at": "2024-01-20T22:30:00Z"
}{
"detail": "Session not found"
}Beats
/v1/beatsList beats in a campaign (ordered by index).
Headers
x-api-key*— Your API keyQuery Params
campaign_id*— Campaign IDpage— Page numbersize— Page sizewith_links— Preserve wikilink markupRequest Example
curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/beats?campaign_id=abc123"Responses
{
"data": [
{
"id": "beat_123",
"campaign_id": "camp_abc123",
"game_session_id": "session_456",
"label": "The Final Battle",
"type": "major",
"description": "The party confronts the dark lord",
"index": 1,
"parent_id": null,
"created_at": "2024-01-20T22:30:00Z"
}
],
"total": 48,
"page": 1,
"size": 20,
"pages": 3
}{
"detail": "campaign_id is required"
}/v1/beats/{beat_id}Get a specific beat by ID.
Headers
x-api-key*— Your API keyQuery Params
with_links— Preserve wikilink markupRequest Example
curl -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/beats/beat-123Responses
{
"id": "beat_123",
"campaign_id": "camp_abc123",
"game_session_id": "session_456",
"label": "The Final Battle",
"type": "major",
"description": "The party confronts the dark lord",
"index": 1,
"parent_id": null,
"created_at": "2024-01-20T22:30:00Z"
}{
"detail": "Beat not found"
}/v1/beatsCreate a new beat.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
label*— Beat labeltype*— major, minor, or stepcampaign_id*— Campaign IDgame_session_id— Session IDdescription— Beat descriptionindex— Position within siblingsparent_id— Parent beat ID (for minor/step)Request Example
curl -X POST \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"label": "The Final Battle",
"type": "major",
"campaign_id": "abc123",
"game_session_id": "session-123"
}' \
https://api.myarchivist.ai/v1/beatsResponses
{
"id": "beat_new789",
"campaign_id": "camp_abc123",
"game_session_id": "session_456",
"label": "The Final Battle",
"type": "major",
"description": null,
"index": 1,
"parent_id": null,
"created_at": "2024-01-25T16:45:00Z"
}{
"detail": "label, type, and campaign_id are required"
}/v1/beats/{beat_id}Update a beat (uses JSON Merge Patch).
Headers
x-api-key*— Your API keyContent-Type*— application/merge-patch+jsonRequest Body
label— Beat labeldescription— Beat descriptionindex— Position within siblingsparent_id— Parent beat IDResponses
{
"id": "beat_123",
"campaign_id": "camp_abc123",
"game_session_id": "session_456",
"label": "Updated Beat Label",
"type": "major",
"description": "Updated description",
"index": 2,
"parent_id": null,
"created_at": "2024-01-20T22:30:00Z"
}{
"detail": "Beat not found"
}/v1/beats/{beat_id}Delete a beat (with hierarchy rules).
Headers
x-api-key*— Your API keyResponses
(no content){
"detail": "Beat not found"
}Moments
/v1/momentsList moments in a campaign or session.
Headers
x-api-key*— Your API keyQuery Params
campaign_id— Campaign IDsession_id— Session IDwith_links— Preserve wikilink markupRequest Example
curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/moments?campaign_id=abc123"Responses
{
"data": [
{
"id": "moment_123",
"campaign_id": "camp_abc123",
"session_id": "session_456",
"label": "Epic Quote",
"content": "I am Thorin, son of Thrain...",
"created_at": "2024-01-20T22:30:00Z"
}
],
"total": 156,
"page": 1,
"size": 20,
"pages": 8
}/v1/moments/{moment_id}Get a specific moment by ID.
Headers
x-api-key*— Your API keyQuery Params
with_links— Preserve wikilink markupResponses
{
"id": "moment_123",
"campaign_id": "camp_abc123",
"session_id": "session_456",
"label": "Epic Quote",
"content": "I am Thorin, son of Thrain...",
"created_at": "2024-01-20T22:30:00Z"
}{
"detail": "Moment not found"
}/v1/momentsCreate a new moment.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
label*— Moment labelcampaign_id*— Campaign IDsession_id— Session IDcontent— Moment contentResponses
{
"id": "moment_new999",
"campaign_id": "camp_abc123",
"session_id": "session_456",
"label": "Epic Quote",
"content": "I am Thorin...",
"created_at": "2024-01-25T16:45:00Z"
}{
"detail": "label and campaign_id are required"
}/v1/moments/{moment_id}Update a moment.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonResponses
{
"id": "moment_123",
"campaign_id": "camp_abc123",
"session_id": "session_456",
"label": "Updated Label",
"content": "Updated content...",
"created_at": "2024-01-20T22:30:00Z"
}{
"detail": "Moment not found"
}/v1/moments/{moment_id}Delete a moment.
Headers
x-api-key*— Your API keyResponses
(no content){
"detail": "Moment not found"
}Factions
/v1/factionsList factions in a campaign.
Headers
x-api-key*— Your API keyQuery Params
campaign_id*— Campaign IDwith_links— Preserve wikilink markupRequest Example
curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/factions?campaign_id=abc123"Responses
{
"data": [
{
"id": "faction_123",
"campaign_id": "camp_abc123",
"name": "The Shadow Thieves",
"description": "A guild of thieves operating in the shadows",
"type": "guild",
"created_at": "2024-01-15T10:30:00Z"
}
],
"total": 5,
"page": 1,
"size": 20,
"pages": 1
}{
"detail": "campaign_id is required"
}/v1/factions/{faction_id}Get a specific faction by ID.
Headers
x-api-key*— Your API keyQuery Params
with_links— Preserve wikilink markupResponses
{
"id": "faction_123",
"campaign_id": "camp_abc123",
"name": "The Shadow Thieves",
"description": "A guild of thieves operating in the shadows",
"type": "guild",
"created_at": "2024-01-15T10:30:00Z"
}{
"detail": "Faction not found"
}/v1/factionsCreate a new faction.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
name*— Faction namecampaign_id*— Campaign IDdescription— Faction descriptiontype— Faction typeimage— HTTPS image URL (max 2048 chars)Responses
{
"id": "faction_new456",
"campaign_id": "camp_abc123",
"name": "The Iron Brotherhood",
"description": "A mercenary company",
"type": "guild",
"created_at": "2024-01-25T16:45:00Z"
}{
"detail": "name and campaign_id are required"
}/v1/factions/{faction_id}Update a faction.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
name— Faction namedescription— Faction descriptiontype— Faction typeimage— HTTPS image URL (max 2048 chars)Responses
{
"id": "faction_123",
"campaign_id": "camp_abc123",
"name": "Updated Faction Name",
"description": "Updated description",
"type": "guild",
"created_at": "2024-01-15T10:30:00Z"
}{
"detail": "Faction not found"
}/v1/factions/{faction_id}Delete a faction.
Headers
x-api-key*— Your API keyResponses
(no content){
"detail": "Faction not found"
}Locations
/v1/locationsList locations in a campaign.
Headers
x-api-key*— Your API keyQuery Params
campaign_id*— Campaign IDwith_links— Preserve wikilink markupRequest Example
curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/locations?campaign_id=abc123"Responses
{
"data": [
{
"id": "loc_123",
"campaign_id": "camp_abc123",
"name": "The Prancing Pony",
"description": "A cozy inn in Bree",
"type": "tavern",
"parent_id": "loc_456",
"created_at": "2024-01-15T10:30:00Z"
}
],
"total": 18,
"page": 1,
"size": 20,
"pages": 1
}{
"detail": "campaign_id is required"
}/v1/locations/{location_id}Get a specific location by ID.
Headers
x-api-key*— Your API keyQuery Params
with_links— Preserve wikilink markupResponses
{
"id": "loc_123",
"campaign_id": "camp_abc123",
"name": "The Prancing Pony",
"description": "A cozy inn in Bree",
"type": "tavern",
"parent_id": "loc_456",
"created_at": "2024-01-15T10:30:00Z"
}{
"detail": "Location not found"
}/v1/locationsCreate a new location.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
name*— Location namecampaign_id*— Campaign IDdescription— Location descriptiontype— Location typeparent_id— Parent location IDimage— HTTPS image URL (max 2048 chars)Responses
{
"id": "loc_new789",
"campaign_id": "camp_abc123",
"name": "Rivendell",
"description": "The Last Homely House",
"type": "city",
"parent_id": null,
"created_at": "2024-01-25T16:45:00Z"
}{
"detail": "name and campaign_id are required"
}/v1/locations/{location_id}Update a location.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
name— Location namedescription— Location descriptiontype— Location typeparent_id— Parent location IDimage— HTTPS image URL (max 2048 chars)Responses
{
"id": "loc_123",
"campaign_id": "camp_abc123",
"name": "Updated Location Name",
"description": "Updated description",
"type": "tavern",
"parent_id": "loc_456",
"created_at": "2024-01-15T10:30:00Z"
}{
"detail": "Location not found"
}/v1/locations/{location_id}Delete a location.
Headers
x-api-key*— Your API keyResponses
(no content){
"detail": "Location not found"
}Items
/v1/itemsList items in a campaign.
Headers
x-api-key*— Your API keyQuery Params
campaign_id*— Campaign IDwith_links— Preserve wikilink markupRequest Example
curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/items?campaign_id=abc123"Responses
{
"data": [
{
"id": "item_123",
"campaign_id": "camp_abc123",
"name": "Sting",
"description": "An elven blade that glows blue near orcs",
"type": "weapon",
"created_at": "2024-01-15T10:30:00Z"
}
],
"total": 32,
"page": 1,
"size": 20,
"pages": 2
}{
"detail": "campaign_id is required"
}/v1/items/{item_id}Get a specific item by ID.
Headers
x-api-key*— Your API keyQuery Params
with_links— Preserve wikilink markupResponses
{
"id": "item_123",
"campaign_id": "camp_abc123",
"name": "Sting",
"description": "An elven blade that glows blue near orcs",
"type": "weapon",
"created_at": "2024-01-15T10:30:00Z"
}{
"detail": "Item not found"
}/v1/itemsCreate a new item.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
name*— Item namecampaign_id*— Campaign IDdescription— Item descriptiontype— Item type (weapon, armor, etc)image— HTTPS image URL (max 2048 chars)Responses
{
"id": "item_new456",
"campaign_id": "camp_abc123",
"name": "Anduril",
"description": "The Flame of the West",
"type": "weapon",
"created_at": "2024-01-25T16:45:00Z"
}{
"detail": "name and campaign_id are required"
}/v1/items/{item_id}Update an item.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
name— Item namedescription— Item descriptiontype— Item type (weapon, armor, etc)image— HTTPS image URL (max 2048 chars)Responses
{
"id": "item_123",
"campaign_id": "camp_abc123",
"name": "Updated Item Name",
"description": "Updated description",
"type": "weapon",
"created_at": "2024-01-15T10:30:00Z"
}{
"detail": "Item not found"
}/v1/items/{item_id}Delete an item.
Headers
x-api-key*— Your API keyResponses
(no content){
"detail": "Item not found"
}Quests
/v1/questsList canonical quests in a campaign. Results are paginated and include summary counts, quest status/category, and first/last session provenance when known.
Headers
x-api-key*— Your API keyQuery Params
campaign_id*— Campaign IDpage— Page numbersize— Page sizesearch— Search by quest name, giver, or narrative fieldsstatus— Filter by planned | in-progress | blocked | failed | done | n/aquest_category— Filter by main | side | faction | personal | n/aRequest Example
curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/quests?campaign_id=abc123&status=in-progress"Responses
{
"data": [
{
"id": "quest_123",
"campaign_id": "camp_abc123",
"order_index": 2,
"quest_name": "Recover the Azure Sigil",
"quest_giver": "Aria Voss",
"quest_giver_id": "char_123",
"quest_category": "main",
"status": "in-progress",
"next_action": "Question the ferryman at Blackwake.",
"resolution": null,
"objective_count": 3,
"completed_objective_count": 1,
"progress_entry_count": 2,
"related_entity_count": 3,
"first_session": {
"id": "sess_001",
"number": 4,
"title": "Ashes on the Water",
"session_date": "2025-02-10T02:30:00Z"
},
"last_session": {
"id": "sess_003",
"number": 6,
"title": "The Ferryman's Price",
"session_date": "2025-02-24T02:30:00Z"
},
"created_at": "2025-02-10T03:00:00Z",
"updated_at": "2025-02-24T04:15:00Z"
}
],
"total": 1,
"page": 1,
"size": 20,
"pages": 1
}{
"detail": "Invalid API key"
}{
"detail": "Access denied to this campaign"
}/v1/quests/{quest_id}Get a fully expanded quest by ID, including objectives, progress log entries, related entity refs, and session provenance.
Headers
x-api-key*— Your API keyRequest Example
curl -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/quests/quest_123Responses
{
"id": "quest_123",
"campaign_id": "camp_abc123",
"order_index": 2,
"quest_name": "Recover the Azure Sigil",
"quest_giver": "Aria Voss",
"quest_giver_id": "char_123",
"quest_category": "main",
"status": "in-progress",
"success_definition": "Return the sigil to Aria Voss.",
"failure_conditions": "The sigil is destroyed or delivered to House Merrow.",
"next_action": "Question the ferryman at Blackwake.",
"resolution": null,
"objectives": [
{ "id": "obj_1", "text": "Reach Blackwake alive", "status": "completed", "order": 1 },
{ "id": "obj_2", "text": "Find who bought the sigil", "status": "in-progress", "order": 2 },
{ "id": "obj_3", "text": "Recover the sigil", "status": "pending", "order": 3 }
],
"progress_log": [
"The party tracked the smugglers to Blackwake.",
"A ferryman claimed House Merrow paid for a sealed relic case."
],
"progress_log_entries": [
{
"id": "prog_1",
"text": "The party tracked the smugglers to Blackwake.",
"order": 1,
"session_id": "sess_002",
"session_number": 5,
"session_title": "Salt and Smoke",
"session_date": "2025-02-17T02:30:00Z"
}
],
"related_characters": ["Captain Nera", "Dovan Pike — suspect buyer"],
"related_factions": ["House Merrow"],
"related_locations": ["Blackwake Docks"],
"related_items": ["Azure Sigil"],
"related_entity_refs": [
{
"id": "qe_1",
"entity_type": "character",
"entity_id": "char_456",
"entity_name_snapshot": "Captain Nera",
"label": "Captain Nera",
"order": 1
},
{
"id": "qe_2",
"entity_type": "item",
"entity_id": "item_123",
"entity_name_snapshot": "Azure Sigil",
"label": "Azure Sigil",
"order": 4
}
],
"first_session": {
"id": "sess_001",
"number": 4,
"title": "Ashes on the Water",
"session_date": "2025-02-10T02:30:00Z"
},
"last_session": {
"id": "sess_003",
"number": 6,
"title": "The Ferryman's Price",
"session_date": "2025-02-24T02:30:00Z"
},
"created_at": "2025-02-10T03:00:00Z",
"updated_at": "2025-02-24T04:15:00Z"
}{
"detail": "Quest not found"
}/v1/questsCreate a manual quest. `quest_giver` must match an approved character or faction in the same campaign. If `objectives` are supplied, quest status is recomputed from objective statuses. `related_entity_refs` accepts explicit entity IDs; the convenience arrays (`related_characters`, `related_factions`, etc.) are also accepted.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
campaign_id*— Campaign IDquest_name*— Quest titlequest_giver— Must resolve to an approved character or faction in this campaignquest_category— main | side | faction | personal | n/astatus— planned | in-progress | blocked | failed | done | n/a; ignored when objectives are suppliedsuccess_definition— How the quest succeedsfailure_conditions— How the quest failsnext_action— Immediate next stepresolution— Outcome or conclusion textobjectives— Array of strings or { text, status } objectsprogress_log— Array of progress stringsrelated_characters— Convenience array of related character labelsrelated_factions— Convenience array of related faction labelsrelated_locations— Convenience array of related location labelsrelated_items— Convenience array of related item labelsrelated_entity_refs— Array of { entity_type, entity_id?, entity_name_snapshot?, label? } refsRequest Example
curl -X POST \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"campaign_id": "camp_abc123",
"quest_name": "Recover the Azure Sigil",
"quest_giver": "Aria Voss",
"quest_category": "main",
"objectives": [
{ "text": "Find who bought the sigil", "status": "in-progress" },
{ "text": "Recover the sigil", "status": "pending" }
],
"progress_log": [
"The party tracked the smugglers to Blackwake."
],
"related_entity_refs": [
{ "entity_type": "item", "entity_id": "item_123", "label": "Azure Sigil" },
{ "entity_type": "location", "entity_name_snapshot": "Blackwake Docks", "label": "Blackwake Docks" }
]
}' \
https://api.myarchivist.ai/v1/questsResponses
{
"id": "quest_new456",
"campaign_id": "camp_abc123",
"order_index": 7,
"quest_name": "Recover the Azure Sigil",
"quest_giver": "Aria Voss",
"quest_giver_id": "char_123",
"quest_category": "main",
"status": "in-progress",
"success_definition": null,
"failure_conditions": null,
"next_action": null,
"resolution": null,
"objectives": [
{ "id": "obj_new1", "text": "Find who bought the sigil", "status": "in-progress", "order": 1 },
{ "id": "obj_new2", "text": "Recover the sigil", "status": "pending", "order": 2 }
],
"progress_log": ["The party tracked the smugglers to Blackwake."],
"progress_log_entries": [
{ "id": "prog_new1", "text": "The party tracked the smugglers to Blackwake.", "order": 1, "session_id": null, "session_number": null, "session_title": null, "session_date": null }
],
"related_characters": [],
"related_factions": [],
"related_locations": ["Blackwake Docks"],
"related_items": ["Azure Sigil"],
"related_entity_refs": [
{ "id": "qe_new1", "entity_type": "item", "entity_id": "item_123", "entity_name_snapshot": "Azure Sigil", "label": "Azure Sigil", "order": 1 },
{ "id": "qe_new2", "entity_type": "location", "entity_id": null, "entity_name_snapshot": "Blackwake Docks", "label": "Blackwake Docks", "order": 2 }
],
"first_session": null,
"last_session": null,
"created_at": "2025-03-01T05:00:00Z",
"updated_at": "2025-03-01T05:00:00Z"
}{
"detail": "Quest giver must match an approved character or faction in this campaign"
}{
"detail": "Write access denied to this campaign"
}/v1/quests/{quest_id}Partially update a quest. Omitted fields are left untouched. Supplying `objectives` replaces the full objective list and recomputes quest status from those objective statuses. Supplying `related_entity_refs` replaces the full related-entity set; the type-specific arrays replace only their matching type bucket.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
quest_name— Updated quest titlequest_giver— Updated quest giver; must still resolve to an approved character or factionquest_category— Updated categorystatus— Updated status when objectives are omittedsuccess_definition— Updated success definitionfailure_conditions— Updated failure conditionsnext_action— Updated next actionresolution— Updated resolutionobjectives— Replacement objective listprogress_log— Replacement progress-log listrelated_characters— Replacement related character listrelated_factions— Replacement related faction listrelated_locations— Replacement related location listrelated_items— Replacement related item listrelated_entity_refs— Replacement full related-entity ref listRequest Example
curl -X PATCH \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"next_action": "Break into House Merrow's archive vault.",
"status": "blocked",
"related_factions": ["House Merrow", "Blackwake Dock Union"]
}' \
https://api.myarchivist.ai/v1/quests/quest_123Responses
{
"id": "quest_123",
"campaign_id": "camp_abc123",
"order_index": 2,
"quest_name": "Recover the Azure Sigil",
"quest_giver": "Aria Voss",
"quest_giver_id": "char_123",
"quest_category": "main",
"status": "blocked",
"success_definition": "Return the sigil to Aria Voss.",
"failure_conditions": "The sigil is destroyed or delivered to House Merrow.",
"next_action": "Break into House Merrow's archive vault.",
"resolution": null,
"objectives": [
{ "id": "obj_1", "text": "Reach Blackwake alive", "status": "completed", "order": 1 },
{ "id": "obj_2", "text": "Find who bought the sigil", "status": "in-progress", "order": 2 },
{ "id": "obj_3", "text": "Recover the sigil", "status": "pending", "order": 3 }
],
"progress_log": [
"The party tracked the smugglers to Blackwake.",
"A ferryman claimed House Merrow paid for a sealed relic case."
],
"progress_log_entries": [
{ "id": "prog_1", "text": "The party tracked the smugglers to Blackwake.", "order": 1, "session_id": "sess_002", "session_number": 5, "session_title": "Salt and Smoke", "session_date": "2025-02-17T02:30:00Z" }
],
"related_characters": ["Captain Nera"],
"related_factions": ["House Merrow", "Blackwake Dock Union"],
"related_locations": ["Blackwake Docks"],
"related_items": ["Azure Sigil"],
"related_entity_refs": [
{ "id": "qe_1", "entity_type": "character", "entity_id": "char_456", "entity_name_snapshot": "Captain Nera", "label": "Captain Nera", "order": 1 },
{ "id": "qe_2", "entity_type": "faction", "entity_id": null, "entity_name_snapshot": "House Merrow", "label": "House Merrow", "order": 2 },
{ "id": "qe_3", "entity_type": "faction", "entity_id": null, "entity_name_snapshot": "Blackwake Dock Union", "label": "Blackwake Dock Union", "order": 3 },
{ "id": "qe_4", "entity_type": "location", "entity_id": null, "entity_name_snapshot": "Blackwake Docks", "label": "Blackwake Docks", "order": 4 },
{ "id": "qe_5", "entity_type": "item", "entity_id": "item_123", "entity_name_snapshot": "Azure Sigil", "label": "Azure Sigil", "order": 5 }
],
"first_session": {
"id": "sess_001",
"number": 4,
"title": "Ashes on the Water",
"session_date": "2025-02-10T02:30:00Z"
},
"last_session": {
"id": "sess_003",
"number": 6,
"title": "The Ferryman's Price",
"session_date": "2025-02-24T02:30:00Z"
},
"created_at": "2025-02-10T03:00:00Z",
"updated_at": "2025-03-02T01:15:00Z"
}{
"detail": "quest_name cannot be empty"
}{
"detail": "Quest not found"
}/v1/quests/{quest_id}Delete a quest.
Headers
x-api-key*— Your API keyRequest Example
curl -X DELETE -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/quests/quest_123Responses
(no content){
"detail": "Quest not found"
}Journal Entries
/v1/journalsList journal entries in a campaign. Results are filtered to entries the caller can see: public entries, entries authored by the caller, or entries explicitly shared with the caller.
Headers
x-api-key*— Your API keyQuery Params
campaign_id*— Campaign ID (world_id)page— Page numbersize— Page sizeRequest Example
curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/journals?campaign_id=abc123"Responses
{
"data": [
{
"id": "journal_123",
"world_id": "camp_abc123",
"title": "World History",
"summary": "A high-level overview of the first age...",
"token_count": 3245,
"is_public": false,
"status": "draft",
"tags": ["history"],
"folder_id": "folder_789",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-16T10:30:00Z"
}
],
"total": 8
}{
"detail": "campaign_id is required"
}{
"detail": "Invalid API key"
}/v1/journals/{entry_id}Get a specific journal entry by ID including full content. Responses include the caller’s effective permission level for the entry.
Headers
x-api-key*— Your API keyRequest Example
curl -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/journals/journal_123Responses
{
"id": "journal_123",
"world_id": "camp_abc123",
"title": "World History",
"summary": "A high-level overview of the first age...",
"content": "In the beginning, the gods created the world of Aetheria...",
"content_rich": { "root": { "type": "root", "version": 1, "children": [] } },
"tags": ["history"],
"token_count": 3245,
"is_public": false,
"status": "draft",
"folder_id": "folder_789",
"permission_level": "manage",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-16T10:30:00Z"
}{
"detail": "Journal entry not found"
}{
"detail": "Insufficient permissions"
}/v1/journalsCreate a new journal entry. `content_rich` is canonical when both rich and plain content are supplied, folder IDs must belong to the same world, creator-level manage permission is granted automatically, and wikilinks are extracted/synced from the saved content. Maximum 2,000,000 characters per request. Worlds are capped at 1,000,000 journal tokens; individual entries are capped at 50,000 tokens.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
world_id*— Campaign IDtitle*— Entry titlecontent— Plain text content (max 2M chars)content_rich— Lexical editor state JSON; takes precedence over content when both are presentcontent_metadata— Structured content metadatasummary— Short summarytags— Array of tag stringscover_image— Optional journal cover image URLis_pinned— Pin this entry in the UIis_public— Publicly visible entrystatus— draft | published | archivedpublished_at— Explicit published timestamp; otherwise set automatically when status becomes publishedarchived_at— Explicit archived timestamp; otherwise set automatically when status becomes archivedfolder_id— Folder IDRequest Example
curl -X POST \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"world_id": "camp_abc123",
"title": "World History",
"content": "In the beginning, the gods created the world of Aetheria...",
"tags": ["history"],
"status": "draft"
}' \
https://api.myarchivist.ai/v1/journalsResponses
{
"success": true,
"id": "journal_new456"
}{
"detail": "This journal entry exceeds the per-entry token limit"
}{
"detail": "Write access denied to this world"
}{
"detail": "Journal folder not found"
}{
"detail": "Content too large; max 2000000 characters"
}/v1/journalsUpdate an existing journal entry. `content_rich` remains canonical, embeddings are regenerated when saved content changes, permissions can be added or removed, ownership can be reassigned with `author_id`, and journal wikilinks are re-synced from the saved content.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
id*— Journal entry IDtitle— Updated titlesummary— Updated summarycontent— Updated content (triggers re-embedding)content_rich— Updated Lexical JSON (takes precedence over content)content_metadata— Updated metadata objecttags— Updated tagscover_image— Updated cover image URLis_pinned— Updated pinned stateis_public— Updated visibilitystatus— Updated statuspublished_at— Updated published timestamparchived_at— Updated archived timestampfolder_id— Updated folderauthor_id— Transfer authorship to another user with world accesspermissions— Permission mutation object: { add: [{ user_id, level }], remove: [{ user_id }] }Request Example
curl -X PUT \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"id": "journal_123",
"content": "Updated journal content with [[Cassius Traven]].",
"status": "published",
"permissions": {
"add": [{ "user_id": "user_456", "level": "comment" }],
"remove": []
}
}' \
https://api.myarchivist.ai/v1/journalsResponses
{
"success": true,
"id": "journal_123"
}{
"detail": "Insufficient permissions"
}{
"detail": "Journal entry not found"
}{
"detail": "Cannot remove the current owner from this journal entry."
}/v1/journalsDelete a journal entry and its associated embeddings. Requires manage permission on the entry.
Headers
x-api-key*— Your API keyQuery Params
id*— Journal entry IDRequest Example
curl -X DELETE -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/journals?id=journal_123"Responses
{
"success": true
}{
"detail": "Insufficient permissions"
}{
"detail": "Journal entry not found"
}Journal Folders
/v1/journal-foldersList journal folders for a campaign. Ordered by path and position for tree rendering.
Headers
x-api-key*— Your API keyQuery Params
campaign_id*— Campaign ID (world_id)Request Example
curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/journal-folders?campaign_id=abc123"Responses
{
"data": [
{
"id": "folder_123",
"world_id": "camp_abc123",
"parent_id": null,
"name": "Lore",
"path": "lore",
"description": null,
"position": 0,
"metadata": null,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-16T10:30:00Z"
}
]
}{
"detail": "Access denied to this world"
}{
"detail": "World not found"
}/v1/journal-folders/{folder_id}Get a specific journal folder by ID.
Headers
x-api-key*— Your API keyRequest Example
curl -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/journal-folders/folder_123Responses
{
"id": "folder_123",
"world_id": "camp_abc123",
"parent_id": null,
"name": "Lore",
"path": "lore",
"description": null,
"position": 0,
"metadata": null,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-16T10:30:00Z"
}{
"detail": "Access denied to this world"
}{
"detail": "World not found"
}{
"detail": "Journal folder not found"
}/v1/journal-foldersCreate a new journal folder.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
world_id*— Campaign IDname*— Folder namepath*— Folder path (unique per campaign; normalized, no leading/trailing slashes)parent_id— Parent folder ID (must be in same campaign)description— Folder descriptionposition— Sort position within parentmetadata— Optional metadata JSONRequest Example
curl -X POST \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"world_id": "camp_abc123",
"name": "Lore",
"path": "lore",
"position": 0
}' \
https://api.myarchivist.ai/v1/journal-foldersResponses
{
"success": true,
"id": "folder_456"
}{
"detail": "Invalid parent folder"
}{
"detail": "Folder path already exists for this campaign"
}{
"detail": "Write access denied to this world"
}{
"detail": "World not found"
}/v1/journal-foldersUpdate an existing journal folder.
Headers
x-api-key*— Your API keyContent-Type*— application/jsonRequest Body
id*— Journal folder IDname— Updated namepath— Updated path (unique per campaign; normalized, no leading/trailing slashes)parent_id— Updated parent folder ID (must be in same campaign)description— Updated descriptionposition— Updated positionmetadata— Updated metadata JSONRequest Example
curl -X PUT \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"id": "folder_456",
"name": "Lore Docs",
"path": "lore/docs"
}' \
https://api.myarchivist.ai/v1/journal-foldersResponses
{
"success": true,
"id": "folder_456"
}{
"detail": "Folder cannot be its own parent"
}{
"detail": "Invalid parent folder"
}{
"detail": "Folder path already exists for this campaign"
}{
"detail": "Write access denied to this world"
}{
"detail": "World not found"
}{
"detail": "Journal folder not found"
}/v1/journal-foldersDelete a journal folder.
Headers
x-api-key*— Your API keyQuery Params
id*— Journal folder IDRequest Example
curl -X DELETE -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/journal-folders?id=folder_456"Responses
{
"success": true
}{
"detail": "Write access denied to this world"
}{
"detail": "World not found"
}{
"detail": "Journal folder not found"
}