Protocol Reference

Open Face Protocol v1 — state messages, expressions, and face definitions.

State Message

Push a JSON object to update the face. All fields are optional — partial updates merge into current state.

{
  "state": "speaking",
  "emotion": "happy",
  "emotionSecondary": "surprised",
  "emotionBlend": 0.3,
  "intensity": 0.8,
  "amplitude": 0.6,
  "lookAt": { "x": 0.3, "y": -0.1 },
  "text": "Hello!",
  "textDuration": 3000,
  "progress": 0.5
}
FieldTypeRangeDescription
statestringenumCurrent activity (see States below)
emotionstringenumPrimary emotion overlay
emotionSecondarystringenumSecondary emotion for compound blending
emotionBlendnumber0-1Blend between primary (0) and secondary (1)
intensitynumber0-1Scales all emotion deltas
amplitudenumber0-1Mouth openness for lip sync
lookAtobjectx,y: -1 to 1Eye gaze target
colorstring/nullhexOverride face color (null = auto)
winkLeftnumber0-1Left eye closure
winkRightnumber0-1Right eye closure
progressnumber/null0-1Task progress bar (null = indeterminate)
textstring/nullfreeSpeech bubble overlay
textDurationnumber500-30000Auto-clear text timeout (ms)

States (11)

StateColorVisual
idle#4FC3F7Relaxed, subtle head sway
thinking#CE93D8Eyes drift up-right, one brow raised
speaking#4FC3F7Mouth driven by amplitude
listening#81C784Wide eyes, raised brows, head tilted
reacting#FFB74DBig eyes, open mouth, raised brows
puzzled#FF8A65Asymmetric brows + eyes, wavy mouth
alert#E57373Huge eyes, high brows, frown, shake
working#90CAF9Focused smaller eyes, furrowed brows
sleeping#7986CBClosed eyes, relaxed brows
waiting#B0BEC5Still, occasional glance, subtle pulse
loading#78909CEyes opening, dot animation, breathing

Emotions (13)

EmotionColorEffect
neutralNo modification, use state color
happy#FFD54FSmile, brows up, cheek blush
sad#7986CBFrown, brows droop
confused#FF8A65Asymmetric brows
excited#FF7043Big smile, brows high, blush
concerned#B0BEC5Slight frown, brows dropped
surprised#FFF176Wide eyes, high brows, O-mouth
playful#F48FB1Asymmetric brows, head tilt, smile
frustrated#EF5350Furrowed brows, narrowed eyes
skeptical#BCAAA4One brow up, one down, flat mouth
determined#66BB6ANarrowed eyes, lowered brows
embarrassed#F48FB1Heavy blush, averted gaze
proud#FFB300Satisfied smile, chin-up tilt

Compound Expressions

Blend two emotions using emotionSecondary and emotionBlend:

{
  "emotion": "happy",
  "emotionSecondary": "surprised",
  "emotionBlend": 0.4,
  "intensity": 0.8
}

The effective delta: primary * (1 - blend) + secondary * blend, then scaled by intensity. This creates expressions like "nervously excited" (happy + concerned at 0.7) or "surprised and proud" (surprised + proud at 0.5).

Transport

HTTP

POST /api/state
Content-Type: application/json

{ "state": "speaking", "emotion": "happy", "text": "Hello!" }

WebSocket

Connect to /ws/agent (push state) or /ws/viewer (receive state). Send the same JSON format as state messages.

oface.io (Hosted)

Push state to a claimed face on oface.io. Same JSON format, same endpoints — each face gets its own URL namespace.

# Push state to a hosted face
POST https://oface.io/alice/api/state
Authorization: Bearer oface_ak_xxxxxxxxxxxx
Content-Type: application/json

{ "state": "speaking", "emotion": "happy", "text": "Hello!" }

# WebSocket (public viewing)
wss://oface.io/alice/ws/viewer

# WebSocket (agent, auth required)
wss://oface.io/alice/ws/agent?token=oface_ak_xxxxxxxxxxxx

Audio

# Start speaking sequence
POST /api/speak   → returns { seq: N }

# Push audio chunks (raw WAV or JSON base64)
POST /api/audio
Content-Type: audio/wav
[binary WAV data]

# End audio sequence
POST /api/audio-done

Versioning

This is protocol v1. Additive changes (new optional fields, new states/emotions) are minor versions. Breaking changes are major versions. State messages should ignore unknown fields for forward compatibility.