> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sympana.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How Data Moves Through Sympana

> Understand exactly where data comes from, where it goes, and what field paths to use inside GHL workflows — for both voice calls and messaging.

This page shows the complete data flow for every Sympana operation. If you're unsure why a field is empty, which variable to use, or where data lives — start here.

***

## Voice call data flow

### Outbound call: GHL → Sympana → Voice Provider → GHL

<Steps>
  <Step title="GHL workflow reaches Place Call action" icon="diagram-project">
    GHL sends Sympana the action data:

    * `extras.locationId` — which GHL location
    * `extras.contactId` — which contact to call
    * `data.connection_id` — which Sympana connection to use
    * `data.contact_phone` — the phone number to call
    * `data.contact_name` — the contact's full name
    * `data.contact_first_name`, `data.contact_last_name`, `data.contact_email`
  </Step>

  <Step title="Sympana resolves everything" icon="gear">
    Sympana does the following:

    1. Finds the GHL installation for that location
    2. Loads the selected voice connection
    3. Verifies the connection is active
    4. Loads the Retell or Vapi API key
    5. Chooses the phone number (or uses Smart Selection rotation)
    6. Resolves dynamic variables (contact fields, custom fields, static values)
    7. Loads enabled functions for the connection
  </Step>

  <Step title="Sympana sends call to voice provider" icon="phone">
    Sympana sends a call request to Retell or Vapi with:

    * From number (your outbound number)
    * To number (contact's phone)
    * Agent/assistant ID
    * Dynamic variables (injected into the agent prompt)
    * Function definitions (what tools the agent can use)
    * Webhook URL (where the provider sends results)
  </Step>

  <Step title="AI agent has the conversation" icon="robot">
    The AI agent talks to the contact. During the call, it can use functions — each function call goes: Agent → Voice Provider → Sympana → GHL → Sympana → Voice Provider → Agent.
  </Step>

  <Step title="Call ends, provider sends webhook" icon="satellite-dish">
    When the call finishes, the voice provider sends Sympana a webhook containing:

    * Call ID, status, direction
    * Full transcript
    * Recording URL
    * Call duration
    * Disconnection reason
    * Call summary and sentiment (AI-generated)
    * Custom analysis data (if post-call analysis is configured)
  </Step>

  <Step title="Sympana fires Call Completed trigger" icon="bolt">
    Sympana builds the trigger payload and sends it to all subscribed GHL workflows. Your workflow receives the full call data under `triggerData`.
  </Step>
</Steps>

***

## Where to find voice data in GHL workflows

After the **Call Completed** trigger fires, all data is available under `triggerData`. Here are the field paths you use in GHL workflow actions:

### Most commonly used fields

| GHL field path                                  | What it contains                                   | Example value                                     |
| ----------------------------------------------- | -------------------------------------------------- | ------------------------------------------------- |
| `triggerData.call_summary`                      | AI summary of the call                             | "Customer confirmed interest in the premium plan" |
| `triggerData.call_transcript`                   | Full word-for-word transcript                      | "Agent: Hi John..."                               |
| `triggerData.sentiment`                         | Caller sentiment                                   | "Positive", "Negative", "Neutral"                 |
| `triggerData.call_successful`                   | Whether the call achieved its goal                 | true / false                                      |
| `triggerData.user_spoke`                        | Whether a real person answered (false = voicemail) | true / false                                      |
| `triggerData.call_duration`                     | Call length in seconds                             | 180                                               |
| `triggerData.call_details.recording_url`        | Link to the call recording                         | URL                                               |
| `triggerData.call_details.disconnection_reason` | Why the call ended                                 | "customer\_hung\_up", "voicemail\_reached"        |
| `triggerData.call_details.direction`            | Inbound or outbound                                | "outbound"                                        |

### Contact fields

| GHL field path                   | What it contains |
| -------------------------------- | ---------------- |
| `triggerData.contactId`          | GHL contact ID   |
| `triggerData.customer_name`      | Full name        |
| `triggerData.contact_first_name` | First name       |
| `triggerData.contact_last_name`  | Last name        |
| `triggerData.phone`              | Contact phone    |
| `triggerData.email`              | Contact email    |

### Custom analysis fields

If your voice agent extracts structured data (configured in Retell post-call analysis), it appears in multiple formats:

| GHL field path                     | Format               | Best for                                  |
| ---------------------------------- | -------------------- | ----------------------------------------- |
| `triggerData.custom_analysis_json` | JSON string          | Storing in a custom field                 |
| `triggerData.custom_analysis_text` | Human-readable text  | Adding to notes or SMS                    |
| `triggerData.custom_analysis_flat` | Flat key-value pairs | Branching with If/Else on specific values |
| `triggerData.custom_analysis_data` | Original structure   | Advanced processing                       |

### Agent and call metadata

| GHL field path                          | What it contains                |
| --------------------------------------- | ------------------------------- |
| `triggerData.call_id`                   | Unique call identifier          |
| `triggerData.agent_name`                | Sympana connection name         |
| `triggerData.retell_agent_name`         | Provider agent name             |
| `triggerData.call_analysis_json`        | Full provider analysis as JSON  |
| `triggerData.call_details.provider`     | "retell" or "vapi"              |
| `triggerData.call_details.from_phone`   | Number the call was placed from |
| `triggerData.call_details.to_phone`     | Number that was called          |
| `triggerData.call_details.completed_at` | ISO timestamp of call end       |
| `triggerData.identity_status`           | How the contact was matched     |

***

## Messaging data flow

### Inbound message: Contact → GHL → Sympana → AI → GHL

<Steps>
  <Step title="Contact sends a message" icon="message">
    A contact sends a message through any channel (SMS, WhatsApp, Instagram, Facebook, Webchat, TikTok, Email) to your GHL number/account.
  </Step>

  <Step title="GHL receives the message" icon="inbox">
    The message appears in GHL Conversations.
  </Step>

  <Step title="Sympana fires Message Received trigger" icon="bolt">
    Sympana dispatches the trigger to GHL workflows with the message data.
  </Step>

  <Step title="GHL workflow processes" icon="diagram-project">
    Your workflow decides what to do:

    * Check channel filters (SMS only? WhatsApp only?)
    * Check contact tags (has `ai_msg_enabled`?)
    * If conditions pass → Send AI Message action
  </Step>

  <Step title="Sympana processes the AI message" icon="gear">
    Sympana:

    1. Loads the selected messaging connection
    2. Checks Contact Access rules (allowed/blocked/handoff tags)
    3. Checks if the conversation is paused or handed off
    4. Checks for opt-out keywords
    5. Calls Retell or Vapi chat with the message + dynamic variables
    6. Gets the AI response
  </Step>

  <Step title="AI response sent through GHL" icon="paper-plane">
    Sympana sends the AI response back through GHL Conversations on the same channel the contact used.
  </Step>
</Steps>

***

## Where to find messaging data in GHL workflows

### Message Received trigger fields

| GHL field path                   | What it contains        | Example                                                        |
| -------------------------------- | ----------------------- | -------------------------------------------------------------- |
| `triggerData.contactId`          | GHL contact ID          | "abc123"                                                       |
| `triggerData.phone`              | Contact phone number    | "+15551234567"                                                 |
| `triggerData.customer_name`      | Contact full name       | "John Doe"                                                     |
| `triggerData.contact_first_name` | First name              | "John"                                                         |
| `triggerData.contact_last_name`  | Last name               | "Doe"                                                          |
| `triggerData.channel`            | Message channel         | "sms", "whatsapp", "instagram", "facebook", "webchat", "email" |
| `triggerData.message_body`       | The message text        | "I'd like to schedule an appointment"                          |
| `triggerData.conversation_id`    | GHL conversation ID     | "conv\_xyz"                                                    |
| `triggerData.message_id`         | Message ID              | "msg\_abc"                                                     |
| `triggerData.connection_name`    | Sympana connection name | "SMS Support Agent"                                            |

### Handoff Requested trigger fields

| GHL field path                        | What it contains                   |
| ------------------------------------- | ---------------------------------- |
| `triggerData.contactId`               | GHL contact ID                     |
| `triggerData.phone`                   | Contact phone                      |
| `triggerData.customer_name`           | Contact name                       |
| `triggerData.channel`                 | Which channel                      |
| `triggerData.handoff_reason`          | Why handoff was triggered          |
| `triggerData.handoff_keyword_matched` | The keyword that matched           |
| `triggerData.last_message`            | The message that triggered handoff |
| `triggerData.conversation_id`         | GHL conversation ID                |
| `triggerData.connection_name`         | Sympana connection name            |
| `triggerData.message_count`           | Total messages in the conversation |
| `triggerData.ai_reply_count`          | How many AI replies were sent      |

***

## Function data flow

When the AI agent uses a function during a call or message conversation:

```
AI Agent → "I need to book an appointment"
    ↓
Voice Provider (Retell/Vapi) → sends function call to Sympana
    ↓
Sympana → reads function parameters, loads GHL token
    ↓
Sympana → calls GHL API (create appointment, get contact, etc.)
    ↓
GHL → returns result (appointment ID, contact data, etc.)
    ↓
Sympana → formats result and sends back to voice provider
    ↓
AI Agent → "I've booked your appointment for Tuesday at 2 PM"
```

This happens in real time during the conversation — typically under 2 seconds per function call.

***

## Where data is stored

| Data             | Where it lives                                                |
| ---------------- | ------------------------------------------------------------- |
| Call recordings  | Voice provider (Retell/Vapi) — access via `recording_url`     |
| Call transcripts | Passed through Call Completed trigger — not stored by Sympana |
| Call metadata    | Sympana `calls` table + voice provider dashboard              |
| GHL contact data | GoHighLevel — accessed through Get Contact function           |
| Appointments     | GoHighLevel calendars — managed through appointment functions |
| Message history  | GHL Conversations — Sympana sends AI replies through GHL      |
| Trigger events   | Sympana `ghl_trigger_events` table (for debugging)            |
| OAuth tokens     | Sympana vault (encrypted)                                     |

***

## Common field path mistakes

<AccordionGroup>
  <Accordion title="Using 'transcript' instead of 'call_transcript'" icon="circle-xmark">
    The field is `triggerData.call_transcript`, not `triggerData.transcript`. If your GHL action shows an empty value, check the exact field path.
  </Accordion>

  <Accordion title="Using 'summary' instead of 'call_summary'" icon="circle-xmark">
    The field is `triggerData.call_summary`, not `triggerData.summary`.
  </Accordion>

  <Accordion title="Accessing recording_url at the wrong level" icon="circle-xmark">
    Recording URL is nested: `triggerData.call_details.recording_url`, NOT `triggerData.recording_url`.
  </Accordion>

  <Accordion title="Custom analysis is empty" icon="circle-xmark">
    Custom analysis only appears if you configured post-call analysis in your Retell agent settings. If you haven't set it up, all `custom_analysis_*` fields will be empty.
  </Accordion>

  <Accordion title="user_spoke is false on completed calls" icon="circle-xmark">
    `user_spoke = false` means the call went to voicemail. The call still "completed" — the voicemail just played. Use `user_spoke` to distinguish real conversations from voicemails.
  </Accordion>
</AccordionGroup>

***

## Next steps

<CardGroup cols={2}>
  <Card title="Workflow Recipes" icon="book-open" href="/guides/workflow-recipes">
    Copy-paste workflows using these data fields.
  </Card>

  <Card title="Setup Checklist" icon="list-check" href="/guides/setup-checklist">
    Step-by-step from install to go-live.
  </Card>
</CardGroup>
