Skip to main content

Compile

Compilation is the process that transforms uploaded source texts — documents, transcripts, conversation threads — into the psychological primitives that define a face’s persona. The compiled output is stored in the graph and retrieved at inference time.

Document types

Documents

A document is any source text that describes or characterizes the face from the outside: an interview, biography, essay, article, journal entry, or PDF. Documents are compiled into structured components that express the persona in a minimal formal language.

Threads

A thread is a conversation transcript — a direct record of how the face expresses itself. Threads are compiled differently, capturing speech patterns, response style, and interaction habits.

Compiling a document

Compile a document with a single call to /make. It returns 202 immediately and handles extraction + sync in the background:
curl -X POST https://api.faces.sh/v1/compile/documents/DOC_ID/make \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "document_id": "abc123",
  "alias": "alice",
  "label": "My Document",
  "status": "preparing",
  "chunks_total": 12
}

Polling for progress

Poll GET /v1/compile/documents/DOC_ID every 2-3 seconds to track progress:
curl https://api.faces.sh/v1/compile/documents/DOC_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "document_id": "abc123",
  "alias": "alice",
  "prepare_status": "preparing",
  "chunks_total": 12,
  "chunks_completed": 7,
  "current_counts": {
    "epsilon": 5,
    "beta": 8,
    "delta": 3,
    "alpha": 14
  }
}

Status transitions

null → "preparing" → "syncing" → "synced"
            ↕              ↘
         "paused"        "stalled" → (re-trigger /make) → "preparing" → ...

                         "failed"
StatusMeaning
nullDocument created but not yet compiled (or reset)
"preparing"Extracting knowledge from text chunks
"syncing"Writing extracted knowledge to the graph
"synced"Compilation complete — stop polling
"paused"Compilation paused by user — progress preserved, call /make to resume
"stalled"Temporary API failure — progress saved, call /make again to resume from where it left off
"failed"Unrecoverable error — stop polling
Each chunk is retried automatically with exponential backoff before the compile stalls. A stalled compile preserves all progress — re-triggering /make resumes from the last completed chunk, not from scratch.

Progress fields

FieldDescription
prepare_statusCurrent status (see above)
chunks_totalTotal chunks the document was split into
chunks_completedChunks processed so far
current_countsRunning count of extracted components: {epsilon, beta, delta, alpha}
Billing (compile quota or credit deduction) is handled automatically when sync completes.

Controlling compilation

ActionEndpointEffect
PausePOST /compile/threads/{id}/pauseStop after current chunk. Progress preserved. Resume with /make.
ResetPOST /compile/threads/{id}/resetWipe all extraction progress. Source data preserved. Fresh /make.
DeleteDELETE /compile/threads/{id}Remove thread entirely.
Pause and reset work on documents too (/compile/documents/{id}/pause and /reset).

Lightweight polling

For polling during compilation, use ?status_only=true to get a lightweight response (~170 bytes) without messages or content:
curl "https://api.faces.sh/v1/compile/threads/THREAD_ID?status_only=true" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "id": "thread-uuid",
  "alias": "face-alias",
  "prepare_status": "preparing",
  "chunks_total": 25,
  "chunks_completed": 17,
  "current_counts": {"epsilon": 5, "beta": 8, "delta": 3, "alpha": 14}
}

Listing documents

curl "https://api.faces.sh/v1/compile/documents?alias=FACE_ALIAS" \
  -H "Authorization: Bearer YOUR_API_KEY"

Deleting a document

curl -X DELETE https://api.faces.sh/v1/compile/documents/DOC_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
Deleting a compiled document removes its contribution from the face’s knowledge graph and decrements your compile token usage accordingly.

Uploading threads

A thread is a multi-speaker conversation transcript. Upload a text file with Speaker Name: message format:
Interviewer: Tell me about yourself.
Troy: I'm an inventor living in the Parisian countryside.
Interviewer: What drives your work?
Troy: The conviction that technology should serve human flourishing.
Upload with type=thread and face_speaker to specify which speaker is the face:
curl -X POST "https://api.faces.sh/v1/faces/FACE_ALIAS/upload?type=thread&face_speaker=Troy" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@interview.txt"
The face_speaker parameter maps that speaker to role=user (the face’s voice). All other speakers become role=assistant. If omitted, the first speaker is assumed to be the face. Once uploaded, compile the thread with /make (fire-and-forget — chunked extraction + sync in one step):
curl -X POST https://api.faces.sh/v1/compile/threads/THREAD_ID/make \
  -H "Authorization: Bearer YOUR_API_KEY"
# Returns 202 with status="preparing" and chunks_total

# Poll for progress
curl https://api.faces.sh/v1/compile/threads/THREAD_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
# Response includes prepare_status, chunks_completed, chunks_total, current_counts
# Status transitions: preparing → syncing → synced (or stalled/failed)
Thread compilation uses the same status transitions, progress fields, and retry behavior as documents. If a compile stalls, call /make again to resume from the last completed chunk.

Audio/video threads

Audio and video files uploaded with type=thread are transcribed automatically with speaker diarization. The upload returns 202 immediately — transcription runs in the background. Poll GET /v1/compile/threads/THREAD_ID until prepare_status changes from "transcribing" to null (ready to review). Speakers are labeled automatically (Speaker A, Speaker B, etc.). Use face_speaker=A to map the correct speaker.
# Upload audio/video — returns 202 with prepare_status="transcribing"
curl -X POST "https://api.faces.sh/v1/faces/FACE_ALIAS/upload?type=thread&face_speaker=A" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@interview.mp3"

# Poll until transcription completes
curl https://api.faces.sh/v1/compile/threads/THREAD_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
# prepare_status: "transcribing" → null (ready) or "failed"

# Review the transcript, then compile
curl -X POST https://api.faces.sh/v1/compile/threads/THREAD_ID/make \
  -H "Authorization: Bearer YOUR_API_KEY"
Text file uploads (.txt) are processed synchronously and return 200 with the full transcript immediately.

Interview threads

An interview thread is a live conversation where an AI interviewer asks questions to build the face’s persona in real time. Threads are created and advanced via the compile threads API:
# Start a new interview thread
curl -X POST https://api.faces.sh/v1/compile/threads \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"alias": "FACE_ALIAS", "label": "My Interview"}'

# Send a message
curl -X POST https://api.faces.sh/v1/compile/threads/THREAD_ID/messages \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message": "I believe in testing software thoroughly."}'

# Compile to knowledge graph (sync for live threads, make for uploaded)
curl -X POST https://api.faces.sh/v1/compile/threads/THREAD_ID/sync \
  -H "Authorization: Bearer YOUR_API_KEY"

Interviewer billing source

Interview threads use an LLM to generate interviewer questions. How this is paid for depends on your plan and can be controlled per-request:
SourceWho paysWhen used
oauthYour ChatGPT subscription (free)Connect plan with linked OpenAI account
compileMonthly compile token quotaConnect plan with remaining quota
creditsAPI credit balanceAny plan with positive balance
Default behavior (auto): The system tries each source in order — oauthcompilecredits — and uses the first one available. Explicit override: Pass interviewer_billing_source in the request body to force a specific source:
curl -X POST https://api.faces.sh/v1/compile/threads \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"alias": "FACE_ALIAS", "label": "Interview", "interviewer_billing_source": "compile"}'
The response includes interviewer_billing_source (which path was used) and tokens_charged (compile tokens consumed for this message), so the UI can update usage in real time. If no payment source is available, the endpoint returns 402 with a structured error indicating whether the user needs to connect their OpenAI account, add credits, or both.

Compile quota

Each plan includes a monthly compile quota measured in tokens:
PlanQuotaReset
FreePay-per-token
Connect100,000 tokensEvery 30 days
Quota is shared across all faces in your account. Check your current usage:
curl https://api.faces.sh/v1/billing/compile-quota \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "data": {
    "plan": "connect",
    "tokens_used": 12400,
    "tokens_limit": 100000,
    "resets_at": "2026-04-05T00:00:00Z",
    "faces": [
      {
        "alias": "alice",
        "tokens_in_graph": 8200,
        "tokens_charged_period": 8200,
        "tokens_charged_alltime": 21600
      }
    ]
  }
}

Overflow billing

When you exceed your plan quota, compilation continues but additional tokens are billed to your credit balance at the standard rate for the underlying model. This prevents compile jobs from silently failing when you hit your quota ceiling. If your credit balance is also exhausted, compilation stops and returns 402.

Uploading large files

Text and PDF files can be uploaded directly. Audio and video files are transcribed before compilation — the transcription counts against your credit balance, not your compile quota. For batch imports, consider using the import endpoint or the upload endpoint in a loop.

Compile vs. chat tokens

Compile quota tracks the tokens consumed during compilation (reading and processing your source texts). Chat token usage is separate and billed against your credit balance based on the LLM model used for each conversation.