Interactive code examples for the most common CharacterOS workflows. Select between curl and Python implementations. All examples use Bearer token authentication with your API key.
Upload a manuscript file to create a new project (multipart/form-data)
curl -X POST https://<your-railway-domain>/api/projects/upload-manuscript \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-F "title=Alice in Wonderland" \
-F "description=Classic Victorian fantasy novel" \
-F "file=@alice_in_wonderland.txt"Index a manuscript and extract character profiles (returns job_id — poll /api/jobs/{job_id})
curl -X POST https://<your-railway-domain>/api/characteros/projects/YOUR_PROJECT_ID/build \
-H "Authorization: Bearer YOUR_JWT_TOKEN"Send a message to a canon-locked character in CharacterOS
curl -X POST https://<your-railway-domain>/api/characteros/projects/YOUR_PROJECT_ID/chat \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"character_id": "char_alice",
"message": "Why did you follow the rabbit?",
"mode": "CANON"
}'Generate a multi-character scene with 3-pass continuity validation
curl -X POST https://<your-railway-domain>/api/characteros/projects/YOUR_PROJECT_ID/scene \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"character_ids": ["char_alice", "char_cheshire"],
"prompt": "Alice confronts the Cheshire Cat in the forest about the path to take.",
"scene_type": "dialogue-heavy",
"director_controls": {
"mood": "tense",
"pacing": "moderate",
"intensity": 0.8
}
}'Synthesize multi-voice scene audio through the full production pipeline
curl -X POST https://<your-railway-domain>/api/audio/characteros/projects/YOUR_PROJECT_ID/generate-audio-pipeline \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"character_ids": ["char_alice", "char_cheshire"],
"scene_text": "NARRATOR: The forest was quiet.\nALICE: Where are we?\nCHESHIRE: Everywhere and nowhere.",
"voice_assignments": {
"alice": "voice_01",
"cheshire": "voice_02"
},
"director_controls": {
"mood": "neutral",
"pacing": "moderate",
"intensity": 0.5
},
"output_format": "mp3"
}'Trigger background character reflection for personality evolution
curl -X POST https://<your-railway-domain>/api/characteros/projects/YOUR_PROJECT_ID/characters/char_alice/reflect \
-H "Authorization: Bearer YOUR_JWT_TOKEN"Retrieve project details and current build/analysis status
curl -X GET https://<your-railway-domain>/api/projects/YOUR_PROJECT_ID \
-H "Authorization: Bearer YOUR_JWT_TOKEN"List all API keys for programmatic authentication
curl -X GET https://<your-railway-domain>/api/billing/api-keys \
-H "Authorization: Bearer YOUR_JWT_TOKEN"Generate API keys in your project settings under /api/billing/api-keys. Each key is one-time displayed — store it securely. Use as Bearer token: Authorization: Bearer YOUR_API_KEY. Keys are SHA256-hashed in the database for security.
The backend is hosted on Railway. In production the frontend rewrites /api/* to the Railway origin via NEXT_PUBLIC_API_URL (set in Vercel). For direct API calls, use your Railway backend URL. For local development, use http://localhost:8080.
Rate limiting is enforced per API key via Redis: 100 requests/minute by default. Burst limits are 150 requests/10 seconds. Check response headers X-RateLimit-Remaining and X-RateLimit-Reset for limit info.
All errors return JSON with error_code and recovery_suggestions. Examples: CHARACTER_PROFILE_NOT_FOUND, CANON_RETRIEVAL_FAILED, WRITER_TIMEOUT. Always check HTTP status before using the response body.
All CharacterOS operations require project_id and often character_id. Get these from the project details endpoint or project creation response. IDs are UUIDs or slug-like identifiers (e.g., proj_123abc, char_alice).
Character responses are scoped by mode: CANON (strict source material), CANON+INFER (safe inference), BRANCH (creative exploration), WRITER_ROOM (collaboration mode). Default is CANON.
Long-running operations (build, scene generation, audio synthesis) return immediately with a job_id. Poll GET /api/jobs/<job_id> to check status. Status values: pending, running, completed, failed.