Skip to content

Assistant Speech Ended Event

Triggered after the assistant finishes speaking.

Event Structure

json
{
  "type": "assistant_speech_ended",
  "session": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "account_id": "account-123",
    "phone_number": "+1234567890"
  }
}

Fields

FieldTypeRequiredDescription
typestringYesAlways "assistant_speech_ended"
session.idstring (UUID)YesSession identifier
session.account_idstringYesAccount identifier
session.phone_numberstringYesPhone number for this flow session

Response

You can return any action or 204 No Content. Common uses:

  • Trigger follow-up actions - Continue the conversation flow
  • Track completion - Log that speech finished
  • No response - Just track the event

Examples

Trigger Follow-Up Action

python
@app.route('/webhook', methods=['POST'])
def webhook():
    event = request.json
    session_id = event['session']['id']

    if event['type'] == 'assistant_speech_ended':
        # Trigger next action in conversation flow
        return jsonify({
            'type': 'speak',
            'session_id': session_id,
            'text': 'Is there anything else I can help you with?'
        })

    return '', 204

Track Completion

python
@app.route('/webhook', methods=['POST'])
def webhook():
    event = request.json

    if event['type'] == 'assistant_speech_ended':
        # Log that speech completed
        log_speech_completed(event['session']['id'])
        return '', 204

Node.js

javascript
app.post('/webhook', (req, res) => {
  const event = req.body;

  if (event.type === 'assistant_speech_ended') {
    // Trigger next action
    return res.json({
      type: 'speak',
      session_id: event.session.id,
      text: 'Is there anything else I can help you with?'
    });
  }

  res.status(204).send();
});

Go

go
func webhook(w http.ResponseWriter, r *http.Request) {
    var event map[string]interface{}
    json.NewDecoder(r.Body).Decode(&event)

    if event["type"] == "assistant_speech_ended" {
        session := event["session"].(map[string]interface{})
        action := map[string]interface{}{
            "type":       "speak",
            "session_id": session["id"],
            "text":       "Is there anything else I can help you with?",
        }
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(action)
        return
    }

    w.WriteHeader(http.StatusNoContent)
}

Use Cases

  • Continue conversation - Trigger follow-up questions or actions
  • Track completion - Log that speech playback finished
  • Chain actions - Execute next step in conversation flow
  • Analytics - Track when assistant finishes speaking

Difference from assistant_speak

  • assistant_speak - Triggered when assistant starts speaking (includes duration, text, etc.)
  • assistant_speech_ended - Triggered when assistant finishes speaking (simpler, just session info)

Best Practices

  1. Use for follow-ups - Great for continuing conversation flow
  2. Track timing - Log when speech completes
  3. Chain actions - Trigger next action in sequence
  4. Don't block - Process quickly

Next Steps