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.

ResourceGETPOSTPUTPATCHDELETE
Campaigns
Characters
Sessions
Beats
Moments
Factions
Locations
Items
Journal Entries
Journal Folders
Links
Ask (RAG)

Health

GET/health

Health check for the API service (no auth required).

Request Example

curl https://api.myarchivist.ai/health

Responses

200Service is healthy
{
  "status": "healthy",
  "service": "archivist-api",
  "version": "1.0.0",
  "environment": "production",
  "port": 8000,
  "timestamp": "2025-01-15T10:30:00.123456Z"
}

Ask (RAG)

POST/v1/ask

RAG chat endpoint for campaign questions. Supports chat history and streaming.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

campaign_id*ID of your campaign
messages*Chat messages: [{ role, content }]
streamReturn a streaming response
gm_permissionsWhen true, grant full journal access for the request (overrides asker_id). Defaults to false.
asker_idOptional 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/ask

Responses

200Successful response (non-streaming)
{
  "answer": "Cassius Traven is a shadowy information broker who operates in the city's underground...",
  "monthlyTokensRemaining": 12345,
  "hourlyTokensRemaining": 6789
}
400Bad request - missing required fields
{
  "detail": "messages is required"
}
401Unauthorized - invalid API key
{
  "detail": "Invalid API key"
}
403Forbidden - asker_id lacks campaign access
{
  "detail": "asker_id user does not have access to this world"
}
404Not found - asker_id user missing
{
  "detail": "asker_id user not found"
}
429Rate limit exceeded
{
  "detail": "Monthly token limit exceeded"
}

Campaigns

GET/v1/campaigns

List your campaigns.

Headers

x-api-key*Your API key

Query Params

pagePage number
sizePage size

Request Example

curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/campaigns?page=1&size=10"

Responses

200List of campaigns
{
  "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
}
401Unauthorized - invalid API key
{
  "detail": "Invalid API key"
}
GET/v1/campaigns/{campaign_id}

Get a specific campaign by ID.

Headers

x-api-key*Your API key

Request Example

curl -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/campaigns/abc123

Responses

200Campaign details
{
  "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"
}
404Campaign not found
{
  "detail": "Campaign not found"
}
401Unauthorized - invalid API key
{
  "detail": "Invalid API key"
}
POST/v1/campaigns

Create a new campaign.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

title*Campaign title
descriptionCampaign description
systemGame 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/campaigns

Responses

201Campaign created successfully
{
  "id": "camp_new123",
  "title": "My Epic Campaign",
  "description": "A thrilling adventure",
  "system": "D&D 5e",
  "public": false,
  "created_at": "2024-01-25T16:45:00Z"
}
422Validation error - missing required field
{
  "detail": "title is required"
}
401Unauthorized - invalid API key
{
  "detail": "Invalid API key"
}
PATCH/v1/campaigns/{campaign_id}

Update a campaign.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

titleCampaign title
descriptionCampaign description

Request 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/abc123

Responses

200Campaign updated successfully
{
  "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"
}
404Campaign not found
{
  "detail": "Campaign not found"
}
401Unauthorized
{
  "detail": "Invalid API key"
}
DELETE/v1/campaigns/{campaign_id}

Permanently delete a campaign. This action cannot be undone.

Headers

x-api-key*Your API key

Request Example

curl -X DELETE -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/campaigns/abc123

Responses

204Campaign deleted successfully
(no content)
404Campaign not found
{
  "detail": "Campaign not found"
}
401Unauthorized - invalid API key
{
  "detail": "Invalid API key"
}
GET/v1/campaigns/{campaign_id}/stats

Get campaign statistics (character count, session count, etc).

Headers

x-api-key*Your API key

Request Example

curl -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/campaigns/abc123/stats

Responses

200Campaign statistics
{
  "campaignId": "camp_abc123",
  "characters": 12,
  "sessions": 24,
  "moments": 156,
  "beats": 48,
  "factions": 5,
  "locations": 18,
  "items": 32
}
404Campaign not found
{
  "detail": "Campaign not found"
}
POST/v1/campaigns/{campaign_id}/links

Create a link between two entities.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

from_id*Source entity ID
from_type*Source entity type (Character, Location, etc)
to_id*Target entity ID
to_type*Target entity type
aliasRelationship label

Responses

201Link created successfully
{
  "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"
}
422Validation error
{
  "detail": "from_id and to_id are required"
}

Characters

GET/v1/characters

List characters filtered by campaign.

Headers

x-api-key*Your API key

Query Params

campaign_id*Campaign ID
searchSearch by name
character_typePC, NPC, etc.
approved_onlyFilter approved (default true)
with_linksPreserve wikilink markup

Request Example

curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/characters?campaign_id=abc123"

Responses

200List of characters
{
  "data": [
    {
      "id": "char_123",
      "campaign_id": "camp_abc123",
      "character_name": "Thorin Ironforge",
      "player_name": "John Smith",
      "description": "A brave dwarf warrior",
      "type": "PC",
      "approved": true,
      "created_at": "2024-01-15T10:30:00Z"
    }
  ],
  "total": 1,
  "page": 1,
  "size": 20,
  "pages": 1
}
422Missing required campaign_id
{
  "detail": "campaign_id is required"
}
401Unauthorized
{
  "detail": "Invalid API key"
}
GET/v1/characters/{character_id}

Get a specific character by ID.

Headers

x-api-key*Your API key

Query Params

with_linksPreserve wikilink markup

Request Example

curl -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/characters/char-123

Responses

200Character details
{
  "id": "char_123",
  "campaign_id": "camp_abc123",
  "character_name": "Thorin Ironforge",
  "player_name": "John Smith",
  "description": "A brave dwarf warrior",
  "type": "PC",
  "approved": true,
  "created_at": "2024-01-15T10:30:00Z"
}
404Character not found
{
  "detail": "Character not found"
}
POST/v1/characters

Create a new character.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

character_name*Character name
campaign_id*Campaign ID
player_namePlayer name
descriptionCharacter description
typePC, NPC, etc.
imageHTTPS 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",
    "player_name": "John Smith",
    "description": "A brave dwarf warrior",
    "type": "PC",
    "campaign_id": "abc123"
  }' \
  https://api.myarchivist.ai/v1/characters

Responses

201Character created successfully
{
  "id": "char_new456",
  "campaign_id": "camp_abc123",
  "character_name": "Thorin Ironforge",
  "player_name": "John Smith",
  "description": "A brave dwarf warrior",
  "type": "PC",
  "approved": false,
  "created_at": "2024-01-25T16:45:00Z"
}
422Validation error - missing required fields
{
  "detail": "character_name and campaign_id are required"
}
422Validation error - HTTP URL not allowed for image
{
  "detail": "image must be an HTTPS URL"
}
404Campaign not found
{
  "detail": "Campaign not found"
}
PATCH/v1/characters/{character_id}

Update a character.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

character_nameCharacter name
descriptionCharacter description
imageHTTPS image URL (max 2048 chars)

Responses

200Character updated successfully
{
  "id": "char_123",
  "campaign_id": "camp_abc123",
  "character_name": "Thorin Ironforge the Bold",
  "player_name": "John Smith",
  "description": "A brave dwarf warrior with a legendary magic axe",
  "type": "PC",
  "approved": true,
  "created_at": "2024-01-15T10:30:00Z"
}
404Character not found
{
  "detail": "Character not found"
}
DELETE/v1/characters/{character_id}

Delete a character.

Headers

x-api-key*Your API key

Responses

204Character deleted successfully
(no content)
404Character not found
{
  "detail": "Character not found"
}

Sessions

GET/v1/sessions

List sessions in a campaign.

Headers

x-api-key*Your API key

Query Params

campaign_id*Campaign ID
session_typeaudioUpload, playByPost, discordVoice, etc.
public_onlyShow only public sessions
with_linksPreserve wikilink markup

Request Example

curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/sessions?campaign_id=abc123"

Responses

200List of game sessions
{
  "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
}
422Missing required campaign_id
{
  "detail": "campaign_id is required"
}
GET/v1/sessions/{session_id}

Get a specific session by ID.

Headers

x-api-key*Your API key

Query Params

include_beatsInclude related beats
include_momentsInclude related moments
with_linksPreserve wikilink markup

Request Example

curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/sessions/session-123?include_beats=true"

Responses

200Session details
{
  "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"
}
404Session not found
{
  "detail": "Session not found"
}
GET/v1/sessions/{session_id}/cast-analysis

Get stored cast analysis data for a session.

Headers

x-api-key*Your API key

Request Example

curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/sessions/session-123/cast-analysis"

Responses

200Cast analysis payload
{
  "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"
}
404Cast analysis not found
{
  "detail": "Cast analysis not found"
}
PATCH/v1/sessions/{session_id}

Update a session (title, summary, or session_date only).

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

titleSession title
summarySession summary
session_dateISO datetime

Responses

200Session updated successfully
{
  "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"
}
404Session not found
{
  "detail": "Session not found"
}

Beats

GET/v1/beats

List beats in a campaign (ordered by index).

Headers

x-api-key*Your API key

Query Params

campaign_id*Campaign ID
pagePage number
sizePage size
with_linksPreserve wikilink markup

Request Example

curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/beats?campaign_id=abc123"

Responses

200List of beats
{
  "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
}
422Missing required campaign_id
{
  "detail": "campaign_id is required"
}
GET/v1/beats/{beat_id}

Get a specific beat by ID.

Headers

x-api-key*Your API key

Query Params

with_linksPreserve wikilink markup

Request Example

curl -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/beats/beat-123

Responses

200Beat details
{
  "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"
}
404Beat not found
{
  "detail": "Beat not found"
}
POST/v1/beats

Create a new beat.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

label*Beat label
type*major, minor, or step
campaign_id*Campaign ID
game_session_idSession ID
descriptionBeat description
indexPosition within siblings
parent_idParent 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/beats

Responses

201Beat created successfully
{
  "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"
}
422Validation error
{
  "detail": "label, type, and campaign_id are required"
}
PATCH/v1/beats/{beat_id}

Update a beat (uses JSON Merge Patch).

Headers

x-api-key*Your API key
Content-Type*application/merge-patch+json

Request Body

labelBeat label
descriptionBeat description
indexPosition within siblings
parent_idParent beat ID

Responses

200Beat updated successfully
{
  "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"
}
404Beat not found
{
  "detail": "Beat not found"
}
DELETE/v1/beats/{beat_id}

Delete a beat (with hierarchy rules).

Headers

x-api-key*Your API key

Responses

204Beat deleted successfully
(no content)
404Beat not found
{
  "detail": "Beat not found"
}

Moments

GET/v1/moments

List moments in a campaign or session.

Headers

x-api-key*Your API key

Query Params

campaign_idCampaign ID
session_idSession ID
with_linksPreserve wikilink markup

Request Example

curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/moments?campaign_id=abc123"

Responses

200List of moments
{
  "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
}
GET/v1/moments/{moment_id}

Get a specific moment by ID.

Headers

x-api-key*Your API key

Query Params

with_linksPreserve wikilink markup

Responses

200Moment details
{
  "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"
}
404Moment not found
{
  "detail": "Moment not found"
}
POST/v1/moments

Create a new moment.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

label*Moment label
campaign_id*Campaign ID
session_idSession ID
contentMoment content

Responses

201Moment created successfully
{
  "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"
}
422Validation error
{
  "detail": "label and campaign_id are required"
}
PATCH/v1/moments/{moment_id}

Update a moment.

Headers

x-api-key*Your API key
Content-Type*application/json

Responses

200Moment updated successfully
{
  "id": "moment_123",
  "campaign_id": "camp_abc123",
  "session_id": "session_456",
  "label": "Updated Label",
  "content": "Updated content...",
  "created_at": "2024-01-20T22:30:00Z"
}
404Moment not found
{
  "detail": "Moment not found"
}
DELETE/v1/moments/{moment_id}

Delete a moment.

Headers

x-api-key*Your API key

Responses

204Moment deleted successfully
(no content)
404Moment not found
{
  "detail": "Moment not found"
}

Factions

GET/v1/factions

List factions in a campaign.

Headers

x-api-key*Your API key

Query Params

campaign_id*Campaign ID
with_linksPreserve wikilink markup

Request Example

curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/factions?campaign_id=abc123"

Responses

200List of factions
{
  "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
}
422Missing required campaign_id
{
  "detail": "campaign_id is required"
}
GET/v1/factions/{faction_id}

Get a specific faction by ID.

Headers

x-api-key*Your API key

Query Params

with_linksPreserve wikilink markup

Responses

200Faction details
{
  "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"
}
404Faction not found
{
  "detail": "Faction not found"
}
POST/v1/factions

Create a new faction.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

name*Faction name
campaign_id*Campaign ID
descriptionFaction description
typeFaction type
imageHTTPS image URL (max 2048 chars)

Responses

201Faction created successfully
{
  "id": "faction_new456",
  "campaign_id": "camp_abc123",
  "name": "The Iron Brotherhood",
  "description": "A mercenary company",
  "type": "guild",
  "created_at": "2024-01-25T16:45:00Z"
}
422Validation error
{
  "detail": "name and campaign_id are required"
}
PATCH/v1/factions/{faction_id}

Update a faction.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

nameFaction name
descriptionFaction description
typeFaction type
imageHTTPS image URL (max 2048 chars)

Responses

200Faction updated successfully
{
  "id": "faction_123",
  "campaign_id": "camp_abc123",
  "name": "Updated Faction Name",
  "description": "Updated description",
  "type": "guild",
  "created_at": "2024-01-15T10:30:00Z"
}
404Faction not found
{
  "detail": "Faction not found"
}
DELETE/v1/factions/{faction_id}

Delete a faction.

Headers

x-api-key*Your API key

Responses

204Faction deleted successfully
(no content)
404Faction not found
{
  "detail": "Faction not found"
}

Locations

GET/v1/locations

List locations in a campaign.

Headers

x-api-key*Your API key

Query Params

campaign_id*Campaign ID
with_linksPreserve wikilink markup

Request Example

curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/locations?campaign_id=abc123"

Responses

200List of locations
{
  "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
}
422Missing required campaign_id
{
  "detail": "campaign_id is required"
}
GET/v1/locations/{location_id}

Get a specific location by ID.

Headers

x-api-key*Your API key

Query Params

with_linksPreserve wikilink markup

Responses

200Location details
{
  "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"
}
404Location not found
{
  "detail": "Location not found"
}
POST/v1/locations

Create a new location.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

name*Location name
campaign_id*Campaign ID
descriptionLocation description
typeLocation type
parent_idParent location ID
imageHTTPS image URL (max 2048 chars)

Responses

201Location created successfully
{
  "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"
}
422Validation error
{
  "detail": "name and campaign_id are required"
}
PATCH/v1/locations/{location_id}

Update a location.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

nameLocation name
descriptionLocation description
typeLocation type
parent_idParent location ID
imageHTTPS image URL (max 2048 chars)

Responses

200Location updated successfully
{
  "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"
}
404Location not found
{
  "detail": "Location not found"
}
DELETE/v1/locations/{location_id}

Delete a location.

Headers

x-api-key*Your API key

Responses

204Location deleted successfully
(no content)
404Location not found
{
  "detail": "Location not found"
}

Items

GET/v1/items

List items in a campaign.

Headers

x-api-key*Your API key

Query Params

campaign_id*Campaign ID
with_linksPreserve wikilink markup

Request Example

curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/items?campaign_id=abc123"

Responses

200List of items
{
  "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
}
422Missing required campaign_id
{
  "detail": "campaign_id is required"
}
GET/v1/items/{item_id}

Get a specific item by ID.

Headers

x-api-key*Your API key

Query Params

with_linksPreserve wikilink markup

Responses

200Item details
{
  "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"
}
404Item not found
{
  "detail": "Item not found"
}
POST/v1/items

Create a new item.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

name*Item name
campaign_id*Campaign ID
descriptionItem description
typeItem type (weapon, armor, etc)
imageHTTPS image URL (max 2048 chars)

Responses

201Item created successfully
{
  "id": "item_new456",
  "campaign_id": "camp_abc123",
  "name": "Anduril",
  "description": "The Flame of the West",
  "type": "weapon",
  "created_at": "2024-01-25T16:45:00Z"
}
422Validation error
{
  "detail": "name and campaign_id are required"
}
PATCH/v1/items/{item_id}

Update an item.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

nameItem name
descriptionItem description
typeItem type (weapon, armor, etc)
imageHTTPS image URL (max 2048 chars)

Responses

200Item updated successfully
{
  "id": "item_123",
  "campaign_id": "camp_abc123",
  "name": "Updated Item Name",
  "description": "Updated description",
  "type": "weapon",
  "created_at": "2024-01-15T10:30:00Z"
}
404Item not found
{
  "detail": "Item not found"
}
DELETE/v1/items/{item_id}

Delete an item.

Headers

x-api-key*Your API key

Responses

204Item deleted successfully
(no content)
404Item not found
{
  "detail": "Item not found"
}

Journal Entries

GET/v1/journals

List journal entries in a campaign. Returns summaries without full content.

Headers

x-api-key*Your API key

Query Params

campaign_id*Campaign ID (world_id)
pagePage number
sizePage size

Request Example

curl -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/journals?campaign_id=abc123"

Responses

200List of journal entries (content omitted)
{
  "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
}
422Missing required campaign_id
{
  "detail": "campaign_id is required"
}
401Unauthorized
{
  "detail": "Invalid API key"
}
GET/v1/journals/{entry_id}

Get a specific journal entry by ID including full content.

Headers

x-api-key*Your API key

Request Example

curl -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/journals/journal_123

Responses

200Journal entry with full content
{
  "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",
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-16T10:30:00Z"
}
404Journal entry not found
{
  "detail": "Journal entry not found"
}
403Forbidden
{
  "detail": "Insufficient permissions"
}
POST/v1/journals

Create a new journal entry. Content is chunked (1000 tokens, 100 overlap) and embedded for RAG. Maximum 2,000,000 characters per request. World must stay under 1,000,000 token cap; entries are capped at 50,000 tokens.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

world_id*Campaign ID
title*Entry title
contentPlain text content (max 2M chars)
content_richLexical editor state JSON
summaryShort summary
tagsArray of tag strings
is_publicPublicly visible entry
statusdraft | published | archived
folder_idFolder ID

Request 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/journals

Responses

201Journal entry created successfully
{
  "success": true,
  "id": "journal_new456"
}
400Token limits exceeded
{
  "detail": "This journal entry exceeds the per-entry token limit"
}
403Forbidden
{
  "detail": "Write access denied to this world"
}
413Content too large
{
  "detail": "Content too large; max 2000000 characters"
}
PUT/v1/journals

Update an existing journal entry. If content is provided, embeddings are regenerated. Subject to same limits as POST.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

id*Journal entry ID
titleUpdated title
summaryUpdated summary
contentUpdated content (triggers re-embedding)
content_richUpdated Lexical JSON (takes precedence over content)
tagsUpdated tags
is_publicUpdated visibility
statusUpdated status
folder_idUpdated folder

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...",
    "status": "published"
  }' \
  https://api.myarchivist.ai/v1/journals

Responses

200Journal entry updated successfully
{
  "success": true,
  "id": "journal_123"
}
403Forbidden
{
  "detail": "Insufficient permissions"
}
404Journal entry not found
{
  "detail": "Journal entry not found"
}
413Content too large
{
  "detail": "Content too large; max 2000000 characters"
}
DELETE/v1/journals

Delete a journal entry and its associated embeddings.

Headers

x-api-key*Your API key

Query Params

id*Journal entry ID

Request Example

curl -X DELETE -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/journals?id=journal_123"

Responses

200Journal entry deleted successfully
{
  "success": true
}
403Forbidden
{
  "detail": "Insufficient permissions"
}
404Journal entry not found
{
  "detail": "Journal entry not found"
}

Journal Folders

GET/v1/journal-folders

List journal folders for a campaign. Ordered by path and position for tree rendering.

Headers

x-api-key*Your API key

Query 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

200List of journal folders
{
  "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"
    }
  ]
}
403Forbidden
{
  "detail": "Access denied to this world"
}
404World not found
{
  "detail": "World not found"
}
GET/v1/journal-folders/{folder_id}

Get a specific journal folder by ID.

Headers

x-api-key*Your API key

Request Example

curl -H "x-api-key: YOUR_API_KEY" https://api.myarchivist.ai/v1/journal-folders/folder_123

Responses

200Journal folder
{
  "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"
}
403Forbidden
{
  "detail": "Access denied to this world"
}
404World not found
{
  "detail": "World not found"
}
404Journal folder not found
{
  "detail": "Journal folder not found"
}
POST/v1/journal-folders

Create a new journal folder.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

world_id*Campaign ID
name*Folder name
path*Folder path (unique per campaign; normalized, no leading/trailing slashes)
parent_idParent folder ID (must be in same campaign)
descriptionFolder description
positionSort position within parent
metadataOptional metadata JSON

Request 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-folders

Responses

201Journal folder created successfully
{
  "success": true,
  "id": "folder_456"
}
400Invalid parent folder
{
  "detail": "Invalid parent folder"
}
400Duplicate folder path
{
  "detail": "Folder path already exists for this campaign"
}
403Forbidden
{
  "detail": "Write access denied to this world"
}
404World not found
{
  "detail": "World not found"
}
PUT/v1/journal-folders

Update an existing journal folder.

Headers

x-api-key*Your API key
Content-Type*application/json

Request Body

id*Journal folder ID
nameUpdated name
pathUpdated path (unique per campaign; normalized, no leading/trailing slashes)
parent_idUpdated parent folder ID (must be in same campaign)
descriptionUpdated description
positionUpdated position
metadataUpdated metadata JSON

Request 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-folders

Responses

200Journal folder updated successfully
{
  "success": true,
  "id": "folder_456"
}
400Folder cannot be its own parent
{
  "detail": "Folder cannot be its own parent"
}
400Invalid parent folder
{
  "detail": "Invalid parent folder"
}
400Duplicate folder path
{
  "detail": "Folder path already exists for this campaign"
}
403Forbidden
{
  "detail": "Write access denied to this world"
}
404World not found
{
  "detail": "World not found"
}
404Journal folder not found
{
  "detail": "Journal folder not found"
}
DELETE/v1/journal-folders

Delete a journal folder.

Headers

x-api-key*Your API key

Query Params

id*Journal folder ID

Request Example

curl -X DELETE -H "x-api-key: YOUR_API_KEY" "https://api.myarchivist.ai/v1/journal-folders?id=folder_456"

Responses

200Journal folder deleted successfully
{
  "success": true
}
403Forbidden
{
  "detail": "Write access denied to this world"
}
404World not found
{
  "detail": "World not found"
}
404Journal folder not found
{
  "detail": "Journal folder not found"
}