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
}
| Field | Type | Range | Description |
|---|---|---|---|
state | string | enum | Current activity (see States below) |
emotion | string | enum | Primary emotion overlay |
emotionSecondary | string | enum | Secondary emotion for compound blending |
emotionBlend | number | 0-1 | Blend between primary (0) and secondary (1) |
intensity | number | 0-1 | Scales all emotion deltas |
amplitude | number | 0-1 | Mouth openness for lip sync |
lookAt | object | x,y: -1 to 1 | Eye gaze target |
color | string/null | hex | Override face color (null = auto) |
winkLeft | number | 0-1 | Left eye closure |
winkRight | number | 0-1 | Right eye closure |
progress | number/null | 0-1 | Task progress bar (null = indeterminate) |
text | string/null | free | Speech bubble overlay |
textDuration | number | 500-30000 | Auto-clear text timeout (ms) |
States (11)
| State | Color | Visual |
|---|---|---|
idle | #4FC3F7 | Relaxed, subtle head sway |
thinking | #CE93D8 | Eyes drift up-right, one brow raised |
speaking | #4FC3F7 | Mouth driven by amplitude |
listening | #81C784 | Wide eyes, raised brows, head tilted |
reacting | #FFB74D | Big eyes, open mouth, raised brows |
puzzled | #FF8A65 | Asymmetric brows + eyes, wavy mouth |
alert | #E57373 | Huge eyes, high brows, frown, shake |
working | #90CAF9 | Focused smaller eyes, furrowed brows |
sleeping | #7986CB | Closed eyes, relaxed brows |
waiting | #B0BEC5 | Still, occasional glance, subtle pulse |
loading | #78909C | Eyes opening, dot animation, breathing |
Emotions (13)
| Emotion | Color | Effect |
|---|---|---|
neutral | — | No modification, use state color |
happy | #FFD54F | Smile, brows up, cheek blush |
sad | #7986CB | Frown, brows droop |
confused | #FF8A65 | Asymmetric brows |
excited | #FF7043 | Big smile, brows high, blush |
concerned | #B0BEC5 | Slight frown, brows dropped |
surprised | #FFF176 | Wide eyes, high brows, O-mouth |
playful | #F48FB1 | Asymmetric brows, head tilt, smile |
frustrated | #EF5350 | Furrowed brows, narrowed eyes |
skeptical | #BCAAA4 | One brow up, one down, flat mouth |
determined | #66BB6A | Narrowed eyes, lowered brows |
embarrassed | #F48FB1 | Heavy blush, averted gaze |
proud | #FFB300 | Satisfied 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.