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

# Salesbud as a data source

> Bring data from Salesbud to your Lakehouse.

Salesbud is a Brazilian sales-intelligence platform that records your team's meetings and calls, transcribes them and uses AI to generate summaries, template answers, next steps and evaluations of each conversation. It can also capture your sellers' email threads and WhatsApp chats. The connector extracts your company's completed meetings and calls, with their transcripts and template answers, and the email and WhatsApp conversations with their messages, so you can analyze your sales conversations in your Lakehouse.

Salesbud credentials are not self-service: your Salesbud contact issues them for your company and enables API access for it.

## Configuring Salesbud as a Source

In the [Sources](https://app.nekt.ai/sources) tab, click on the "Add source" button located on the top right of your screen. Then, select the Salesbud option from the list of connectors.

Click **Next** and you'll be prompted to add your access.

### 1. Add account access

Salesbud authenticates with an OAuth 2.0 **client credential**: a **Client ID** and a **Client Secret** that belong to your company, not to a user. The connector exchanges them for a short-lived access token on every sync, so there is nothing to renew on your side.

<Warning>Request the credential from your Salesbud contact, and ask them to enable **API access** for your company — without it Salesbud refuses to issue tokens. Salesbud shows the secret only once, when the credential is created, and cannot recover it. If it is lost, ask for the credential to be rotated.</Warning>

<Note>What the connector can read depends on the **permissions (scopes)** of the credential: `meetings.read`, `calls.read`, `transcriptions.read`, `emails.read`, `emails.content.read`, `whatsapp.read`, and `whatsapp.content.read`. Ask for the ones matching the streams you want. A stream whose permission is missing is skipped with a warning on the run log, and the rest of the sync proceeds normally. We recommend a credential dedicated to Nekt, so rotating or revoking it never disturbs your other integrations.</Note>

The following configurations are available:

* **Client ID**: the identifier of the credential issued by Salesbud (it starts with `sb_client_`). Required.

* **Client Secret**: the secret delivered together with the Client ID. Required.

* **Start Date**: the earliest date from which records will be synced: meetings and calls created from this date on, and email and WhatsApp conversations with activity from this date on. Leave it empty to extract the full history.

* **Lookback Days**: how many days are re-read before the last sync point on every run. Salesbud only exposes a meeting once its processing is complete, and keeps enriching it afterwards (evaluation, tags, answers), so recent records are read again to pick up those changes. The default is 7.

* **Requests Per Minute**: how fast the connector may call Salesbud. By default it uses 90% of the quota Salesbud reports for the credential (120 requests per minute unless Salesbud changed it). The quota is shared with the other integrations of your company, so raise it only if you know no other integration needs it.

Once you're done, click **Next**.

### 2. Select streams

Choose which data streams you want to sync. For faster extractions, select only the streams that are relevant to your analysis. You can select entire groups of streams or pick specific ones.

> Tip: The stream can be found more easily by typing its name.

<Info>Answers and transcripts cost one request per meeting or call, and Salesbud limits transcript reads to 60 per minute. The first sync of a large history can therefore take a while when transcripts are selected; the following syncs only re-read the lookback window. The overall evaluation of each meeting and call (status, score, and justification) already comes in the Meetings and Calls tables, with no extra requests.</Info>

Select the streams and click **Next**.

### 3. Configure data streams

Customize how you want your data to appear in your catalog. Select the desired layer where the data will be placed, a folder to organize it inside the layer, a name for each table (which will effectively contain the fetched data) and the type of sync.

* **Layer**: choose between the existing layers on your catalog. This is where you will find your new extracted tables as the extraction runs successfully.
* **Folder**: a folder can be created inside the selected layer to group all tables being created from this new data source.
* **Table name**: we suggest a name, but feel free to customize it. You have the option to add a **prefix** to all tables at once and make this process faster!
* **Sync Type**: all streams support INCREMENTAL. Read more about Sync Types [here](https://docs.nekt.com/get-started/core-concepts/types-of-sync).

Once you are done configuring, click **Next**.

### 4. Configure data source

Describe your data source for easy identification within your organization, not exceeding 140 characters.

To define your [Trigger](https://docs.nekt.com/get-started/core-concepts/triggers), consider how often you want data to be extracted from this source. This decision usually depends on how frequently you need the new table data updated (every day, once a week, or only at specific times).

Optionally, you can define some additional settings:

* Configure Delta Log Retention and determine for how long we should store old states of this table as it gets updated. Read more about this resource [here](https://docs.nekt.com/get-started/core-concepts/resource-control).
* Determine when to execute an **Additional [Full Sync](https://docs.nekt.com/get-started/core-concepts/types-of-sync#additional-full-sync)**. This will complement the incremental data extractions, ensuring that your data is completely synchronized with your source every once in a while.

<Note>Salesbud's API has no "last changed" filter, so meetings and calls are synced by creation date, re-reading the last **Lookback Days** on every run, and the Lakehouse deduplicates the overlap. A meeting whose processing finishes, or that is re-evaluated, more than that many days after it was created is only picked up by a full sync, so scheduling an occasional additional full sync is recommended. Email and WhatsApp conversations are synced by their latest message; an edited or deleted message is updated when its conversation is read again.</Note>

Once you are ready, click **Next** to finalize the setup.

### 5. Check your new source

You can view your new source on the [Sources](https://app.nekt.ai/sources) page. If needed, manually trigger the source extraction by clicking on the arrow button. Once executed, your data will appear in your Catalog.

<Warning>For you to be able to see it on your [Catalog](https://app.nekt.ai/catalog), you need at least one successful source run.</Warning>

# Streams and Fields

Below you'll find all available data streams from Salesbud and their corresponding fields. API reference: [Salesbud API](https://docs.salesbud.com.br).

<AccordionGroup>
  <Accordion title="Meetings">
    Every completed meeting of your company: recorded by the Salesbud bot, uploaded to the platform or captured by the mobile app (`GET /v1/meetings`). Requires the `meetings.read` permission.

    Primary key: `id` · Replication key: `created_at`

    | Field                              | Type     | Description                                                                                                                                                                                                        |
    | :--------------------------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `id`                               | String   | Opaque identifier of the meeting (prefixed mtg\_).                                                                                                                                                                 |
    | `object`                           | String   | Resource type: 'meeting' for bot-recorded or uploaded conversations, 'call' for conversations captured from a VoIP integration.                                                                                    |
    | `title`                            | String   | Title of the meeting, sanitized.                                                                                                                                                                                   |
    | `status`                           | String   | Processing status; only completed records are exposed by the API.                                                                                                                                                  |
    | `type`                             | String   | Media the record was captured as (video or audio). Independent of the resource kind: a call can be video and a meeting can be audio.                                                                               |
    | `audience`                         | String   | Whether the conversation had participants from outside the company (external) or only internal ones (internal).                                                                                                    |
    | `meeting_at`                       | Datetime | Instant (UTC) the meeting happened.                                                                                                                                                                                |
    | `duration_seconds`                 | Integer  | Duration of the meeting, in seconds.                                                                                                                                                                               |
    | `no_show`                          | Boolean  | Whether the meeting had no attendee.                                                                                                                                                                               |
    | `participants`                     | String   | External participants (JSON array of objects with display\_name, email, phone and kind). On calls usually a single entry with a phone number.                                                                      |
    | `owner_id`                         | String   | Opaque identifier of the user the meeting belongs to. Company scoping follows this user's default company.                                                                                                         |
    | `owner_name`                       | String   | Display name of the owner.                                                                                                                                                                                         |
    | `owner_email`                      | String   | Lowercase email of the owner; null when legacy data is malformed.                                                                                                                                                  |
    | `owner_team_id`                    | String   | Opaque identifier of the owner's default team in the company.                                                                                                                                                      |
    | `owner_team_name`                  | String   | Name of the owner's team.                                                                                                                                                                                          |
    | `owner_team_role`                  | String   | Role of the owner in the team (participant, leadership or observer).                                                                                                                                               |
    | `owner_team_is_default`            | Boolean  | Whether the reported team is the owner's default team in the company; false when the owner has no default team there and another one was reported.                                                                 |
    | `template_id`                      | String   | Opaque identifier of the meeting template, when one was applied.                                                                                                                                                   |
    | `template_name`                    | String   | Display name of the template.                                                                                                                                                                                      |
    | `template_answers`                 | String   | Template questions and the answers generated for them (JSON array of objects with field, question and answer). The meeting\_answers and call\_answers streams carry the same answers with question type and order. |
    | `tags`                             | String   | Tags applied to the record (JSON array of objects with id and name).                                                                                                                                               |
    | `customer_questions`               | String   | Questions the customer asked during the conversation (JSON array of objects with question and category).                                                                                                           |
    | `competitors`                      | String   | Competitors mentioned in the conversation, as registered by the company (JSON array of objects with id and name).                                                                                                  |
    | `enablement_next_steps`            | String   | Next steps agreed in the conversation, or null when none were identified.                                                                                                                                          |
    | `enablement_meeting_type`          | String   | Sales stage the conversation was classified as (qualification, negotiation, proposal, closing, technical\_meeting, questions\_clarifications), or null. Often null on calls.                                       |
    | `enablement_speaking_duration`     | String   | How long each side spoke (JSON object with users — one entry per company user who spoke, with duration\_seconds — and others\_seconds for everyone outside the company).                                           |
    | `accounts`                         | String   | Company-scoped accounts linked to the record (JSON array of objects with id, domain and cnpj).                                                                                                                     |
    | `overall_evaluation_status`        | String   | Processing state of the overall evaluation (not\_started, processing, completed or failed).                                                                                                                        |
    | `overall_evaluation_score`         | Integer  | Overall evaluation score from 0 to 10, when the completed evaluation has one.                                                                                                                                      |
    | `overall_evaluation_justification` | String   | Why the overall score was given; null until the evaluation completes.                                                                                                                                              |
    | `skill_scores`                     | String   | Per-skill scores (JSON array of objects with user, skill, score from 0 to 10 and justification); empty when no skill evaluation exists.                                                                            |
    | `transcript_available`             | Boolean  | Whether a transcript can be read for this record.                                                                                                                                                                  |
    | `transcript_status`                | String   | Processing state of the transcript (completed, not\_started, processing or failed).                                                                                                                                |
    | `created_at`                       | Datetime | Instant (UTC) the meeting entered Salesbud, used as the incremental replication key.                                                                                                                               |
    | `updated_at`                       | Datetime | Instant (UTC) of the last change to the record itself. Informational only: it does not move when a transcript, tag or answer changes.                                                                              |
    | `bot_history`                      | String   | Events of the recording bot (JSON array of objects with code, subcode and occurred\_at).                                                                                                                           |
  </Accordion>

  <Accordion title="Meeting Answers">
    One row per template question answered in a meeting (`GET /v1/meetings/{id}/answers`), with the question type and order. Only requested for meetings that have a template. Requires `meetings.read`.

    Primary key: `id` · Replication key: `updated_at`

    | Field            | Type     | Description                                                                                                                                                  |
    | :--------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `id`             | String   | Opaque identifier of the answer.                                                                                                                             |
    | `meeting_id`     | String   | Identifier of the meeting the answer belongs to.                                                                                                             |
    | `object`         | String   | Resource type; always meeting\_answer, including for calls.                                                                                                  |
    | `question_id`    | String   | Opaque identifier of the template question, stable across records that share the template — key on it rather than on the text, which the company can reword. |
    | `question_text`  | String   | Question text as the template asks it, sanitized.                                                                                                            |
    | `question_type`  | String   | What the template expects as an answer (text, option, multi\_select, boolean or number); the answer always arrives as text, so this says how to parse it.    |
    | `question_order` | Integer  | Position of the question in the template, starting at zero.                                                                                                  |
    | `answer`         | String   | Answer generated for the question.                                                                                                                           |
    | `updated_at`     | Datetime | Instant (UTC) the answer last changed, used as the incremental replication key.                                                                              |
  </Accordion>

  <Accordion title="Meeting Transcripts">
    The transcript of each meeting that has one (`GET /v1/meetings/{id}/transcript`), in the enhanced version when available. Requires `meetings.read` and `transcriptions.read`.

    Primary key: `meeting_id` · Replication key: `updated_at`

    | Field             | Type     | Description                                                                                                                                     |
    | :---------------- | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------- |
    | `meeting_id`      | String   | Identifier of the meeting the transcript belongs to.                                                                                            |
    | `object`          | String   | Resource type; always transcript, including for calls.                                                                                          |
    | `available`       | Boolean  | Whether there is a transcript to read.                                                                                                          |
    | `status`          | String   | Processing state; always completed while available is true, otherwise why the transcript is not there yet (not\_started, processing or failed). |
    | `variant`         | String   | Which transcript was returned: enhanced when the improved version exists, original otherwise.                                                   |
    | `utterance_count` | Integer  | Number of utterances in the transcript.                                                                                                         |
    | `utterances`      | String   | The transcript in chronological order (JSON array of objects with speaker, text, start\_ms and end\_ms offsets in milliseconds), sanitized.     |
    | `created_at`      | Datetime | Instant (UTC) the transcript was first stored.                                                                                                  |
    | `updated_at`      | Datetime | Instant (UTC) the transcript last changed, used as the incremental replication key.                                                             |
  </Accordion>

  <Accordion title="Calls">
    Every completed call captured from a VoIP integration (`GET /v1/calls`). Calls carry the same fields as meetings, except the recording bot history. Requires `calls.read`.

    Primary key: `id` · Replication key: `created_at`

    | Field                              | Type     | Description                                                                                                                                                                                                        |
    | :--------------------------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `id`                               | String   | Opaque identifier of the call (prefixed call\_).                                                                                                                                                                   |
    | `object`                           | String   | Resource type: 'meeting' for bot-recorded or uploaded conversations, 'call' for conversations captured from a VoIP integration.                                                                                    |
    | `title`                            | String   | Title of the call, sanitized.                                                                                                                                                                                      |
    | `status`                           | String   | Processing status; only completed records are exposed by the API.                                                                                                                                                  |
    | `type`                             | String   | Media the record was captured as (video or audio). Independent of the resource kind: a call can be video and a meeting can be audio.                                                                               |
    | `audience`                         | String   | Whether the conversation had participants from outside the company (external) or only internal ones (internal).                                                                                                    |
    | `meeting_at`                       | Datetime | Instant (UTC) the call happened.                                                                                                                                                                                   |
    | `duration_seconds`                 | Integer  | Duration of the call, in seconds.                                                                                                                                                                                  |
    | `no_show`                          | Boolean  | Whether the call had no attendee.                                                                                                                                                                                  |
    | `participants`                     | String   | External participants (JSON array of objects with display\_name, email, phone and kind). On calls usually a single entry with a phone number.                                                                      |
    | `owner_id`                         | String   | Opaque identifier of the user the call belongs to. Company scoping follows this user's default company.                                                                                                            |
    | `owner_name`                       | String   | Display name of the owner.                                                                                                                                                                                         |
    | `owner_email`                      | String   | Lowercase email of the owner; null when legacy data is malformed.                                                                                                                                                  |
    | `owner_team_id`                    | String   | Opaque identifier of the owner's default team in the company.                                                                                                                                                      |
    | `owner_team_name`                  | String   | Name of the owner's team.                                                                                                                                                                                          |
    | `owner_team_role`                  | String   | Role of the owner in the team (participant, leadership or observer).                                                                                                                                               |
    | `owner_team_is_default`            | Boolean  | Whether the reported team is the owner's default team in the company; false when the owner has no default team there and another one was reported.                                                                 |
    | `template_id`                      | String   | Opaque identifier of the call template, when one was applied.                                                                                                                                                      |
    | `template_name`                    | String   | Display name of the template.                                                                                                                                                                                      |
    | `template_answers`                 | String   | Template questions and the answers generated for them (JSON array of objects with field, question and answer). The meeting\_answers and call\_answers streams carry the same answers with question type and order. |
    | `tags`                             | String   | Tags applied to the record (JSON array of objects with id and name).                                                                                                                                               |
    | `customer_questions`               | String   | Questions the customer asked during the conversation (JSON array of objects with question and category).                                                                                                           |
    | `competitors`                      | String   | Competitors mentioned in the conversation, as registered by the company (JSON array of objects with id and name).                                                                                                  |
    | `enablement_next_steps`            | String   | Next steps agreed in the conversation, or null when none were identified.                                                                                                                                          |
    | `enablement_meeting_type`          | String   | Sales stage the conversation was classified as (qualification, negotiation, proposal, closing, technical\_meeting, questions\_clarifications), or null. Often null on calls.                                       |
    | `enablement_speaking_duration`     | String   | How long each side spoke (JSON object with users — one entry per company user who spoke, with duration\_seconds — and others\_seconds for everyone outside the company).                                           |
    | `accounts`                         | String   | Company-scoped accounts linked to the record (JSON array of objects with id, domain and cnpj).                                                                                                                     |
    | `overall_evaluation_status`        | String   | Processing state of the overall evaluation (not\_started, processing, completed or failed).                                                                                                                        |
    | `overall_evaluation_score`         | Integer  | Overall evaluation score from 0 to 10, when the completed evaluation has one.                                                                                                                                      |
    | `overall_evaluation_justification` | String   | Why the overall score was given; null until the evaluation completes.                                                                                                                                              |
    | `skill_scores`                     | String   | Per-skill scores (JSON array of objects with user, skill, score from 0 to 10 and justification); empty when no skill evaluation exists.                                                                            |
    | `transcript_available`             | Boolean  | Whether a transcript can be read for this record.                                                                                                                                                                  |
    | `transcript_status`                | String   | Processing state of the transcript (completed, not\_started, processing or failed).                                                                                                                                |
    | `created_at`                       | Datetime | Instant (UTC) the call entered Salesbud, used as the incremental replication key.                                                                                                                                  |
    | `updated_at`                       | Datetime | Instant (UTC) of the last change to the record itself. Informational only: it does not move when a transcript, tag or answer changes.                                                                              |
  </Accordion>

  <Accordion title="Call Answers">
    One row per template question answered in a call (`GET /v1/calls/{id}/answers`). Only requested for calls that have a template. Requires `calls.read`.

    Primary key: `id` · Replication key: `updated_at`

    | Field            | Type     | Description                                                                                                                                                  |
    | :--------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `id`             | String   | Opaque identifier of the answer.                                                                                                                             |
    | `call_id`        | String   | Identifier of the call the answer belongs to.                                                                                                                |
    | `object`         | String   | Resource type; always meeting\_answer, including for calls.                                                                                                  |
    | `question_id`    | String   | Opaque identifier of the template question, stable across records that share the template — key on it rather than on the text, which the company can reword. |
    | `question_text`  | String   | Question text as the template asks it, sanitized.                                                                                                            |
    | `question_type`  | String   | What the template expects as an answer (text, option, multi\_select, boolean or number); the answer always arrives as text, so this says how to parse it.    |
    | `question_order` | Integer  | Position of the question in the template, starting at zero.                                                                                                  |
    | `answer`         | String   | Answer generated for the question.                                                                                                                           |
    | `updated_at`     | Datetime | Instant (UTC) the answer last changed, used as the incremental replication key.                                                                              |
  </Accordion>

  <Accordion title="Call Transcripts">
    The transcript of each call that has one (`GET /v1/calls/{id}/transcript`). Requires `calls.read` and `transcriptions.read`.

    Primary key: `call_id` · Replication key: `updated_at`

    | Field             | Type     | Description                                                                                                                                     |
    | :---------------- | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------- |
    | `call_id`         | String   | Identifier of the call the transcript belongs to.                                                                                               |
    | `object`          | String   | Resource type; always transcript, including for calls.                                                                                          |
    | `available`       | Boolean  | Whether there is a transcript to read.                                                                                                          |
    | `status`          | String   | Processing state; always completed while available is true, otherwise why the transcript is not there yet (not\_started, processing or failed). |
    | `variant`         | String   | Which transcript was returned: enhanced when the improved version exists, original otherwise.                                                   |
    | `utterance_count` | Integer  | Number of utterances in the transcript.                                                                                                         |
    | `utterances`      | String   | The transcript in chronological order (JSON array of objects with speaker, text, start\_ms and end\_ms offsets in milliseconds), sanitized.     |
    | `created_at`      | Datetime | Instant (UTC) the transcript was first stored.                                                                                                  |
    | `updated_at`      | Datetime | Instant (UTC) the transcript last changed, used as the incremental replication key.                                                             |
  </Accordion>

  <Accordion title="Email Conversations">
    Email threads of the mailboxes your sellers connected to Salesbud, deduplicated across mailboxes (`GET /v1/emails`). Metadata only, no bodies. Requires `emails.read`.

    Primary key: `id` · Replication key: `last_message_at`

    | Field                    | Type     | Description                                                                                                                             |
    | :----------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------- |
    | `id`                     | String   | Opaque identifier of the conversation (prefixed eml\_), stable across mailboxes.                                                        |
    | `object`                 | String   | Resource type; always email\_conversation.                                                                                              |
    | `subject`                | String   | Subject of the first message, sanitized; null when empty.                                                                               |
    | `first_message_at`       | Datetime | Instant (UTC) of the first message of the conversation.                                                                                 |
    | `last_message_at`        | Datetime | Instant (UTC) of the latest message, used as the incremental replication key.                                                           |
    | `message_count`          | Integer  | Number of messages in the conversation.                                                                                                 |
    | `has_attachments`        | Boolean  | Whether any message of the conversation has attachments.                                                                                |
    | `last_message_direction` | String   | Direction of the latest message (inbound or outbound).                                                                                  |
    | `participants`           | String   | Everyone on the thread (JSON array of objects with address, name and internal — true when the address belongs to the company's domain). |
    | `mailboxes`              | String   | Connected company mailboxes that hold a copy of the conversation (JSON array of objects with address and owner).                        |
    | `accounts`               | String   | CRM accounts the conversation is linked to (JSON array of objects with id, domain and cnpj).                                            |
  </Accordion>

  <Accordion title="Email Messages">
    Every message of each email conversation, with its plain-text body and attachment metadata (`GET /v1/emails/{id}/messages`). Requires `emails.read` and `emails.content.read`.

    Primary key: `id` · Replication key: `sent_at`

    | Field             | Type     | Description                                                                                                     |
    | :---------------- | :------- | :-------------------------------------------------------------------------------------------------------------- |
    | `id`              | String   | Opaque identifier of the message.                                                                               |
    | `object`          | String   | Resource type; always email\_message.                                                                           |
    | `conversation_id` | String   | Identifier of the email conversation the message belongs to.                                                    |
    | `sent_at`         | Datetime | Instant (UTC) the message was sent, used as the incremental replication key.                                    |
    | `direction`       | String   | Whether the message was received (inbound) or sent (outbound).                                                  |
    | `subject`         | String   | Subject of the message, sanitized.                                                                              |
    | `snippet`         | String   | Short preview generated by the email provider, sanitized.                                                       |
    | `body_text`       | String   | Plain-text body, sanitized; empty when the message had no text part.                                            |
    | `from_address`    | String   | Lowercase address of the sender.                                                                                |
    | `from_name`       | String   | Display name of the sender as it appeared in the headers.                                                       |
    | `from_internal`   | Boolean  | Whether the sender's domain matches the company's domain.                                                       |
    | `to_recipients`   | String   | Recipients in To (JSON array of objects with address, name and internal).                                       |
    | `cc_recipients`   | String   | Recipients in Cc (JSON array of objects with address, name and internal).                                       |
    | `attachments`     | String   | Attachment metadata (JSON array of objects with filename, mime\_type and size\_bytes); content is never served. |
  </Accordion>

  <Accordion title="WhatsApp Conversations">
    WhatsApp chats of your sellers, captured from WhatsApp Web or RD Conversas (`GET /v1/whatsapp`). Metadata only, no messages. Requires `whatsapp.read`.

    Primary key: `id` · Replication key: `last_message_at`

    | Field                    | Type     | Description                                                                                                                             |
    | :----------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------- |
    | `id`                     | String   | Opaque identifier of the conversation (prefixed wa\_).                                                                                  |
    | `object`                 | String   | Resource type; always whatsapp\_conversation.                                                                                           |
    | `source`                 | String   | Where the chat is captured: whatsapp\_web or rd\_conversas.                                                                             |
    | `is_group`               | Boolean  | Whether the chat is a group.                                                                                                            |
    | `contact_phone`          | String   | E.164 phone of the other side of the chat; null for groups or when the provider hides the number.                                       |
    | `contact_name`           | String   | Display name of the contact, or the group name for groups.                                                                              |
    | `seller_user_id`         | String   | Opaque identifier of the company user whose WhatsApp holds the chat; null when the user is no longer in the company.                    |
    | `seller_user_name`       | String   | Display name of the seller.                                                                                                             |
    | `seller_user_email`      | String   | Lowercase email of the seller.                                                                                                          |
    | `seller_phone`           | String   | E.164 number of the seller's WhatsApp, when the session exposes it.                                                                     |
    | `accounts`               | String   | CRM accounts the conversation is linked to (JSON array of objects with id, domain and cnpj).                                            |
    | `first_message_at`       | Datetime | Instant (UTC) of the oldest visible message; null when the chat has none.                                                               |
    | `last_message_at`        | Datetime | Instant (UTC) of the latest message, used as the incremental replication key. Only a new message moves it — edits and deletions do not. |
    | `last_message_direction` | String   | Direction of the latest message (inbound or outbound).                                                                                  |
    | `deleted_at`             | Datetime | Instant (UTC) the seller deleted the chat, or null.                                                                                     |
    | `deleted_reason`         | String   | Why the chat was deleted (chat\_deleted), or null.                                                                                      |
  </Accordion>

  <Accordion title="WhatsApp Messages">
    Every message of each WhatsApp conversation, with its text, media metadata and audio transcription (`GET /v1/whatsapp/{id}/messages`). Deleted messages stay as rows with empty content. Requires `whatsapp.read` and `whatsapp.content.read`.

    Primary key: `id` · Replication key: `sent_at`

    | Field              | Type     | Description                                                                                                      |
    | :----------------- | :------- | :--------------------------------------------------------------------------------------------------------------- |
    | `id`               | String   | Opaque identifier of the message.                                                                                |
    | `object`           | String   | Resource type; always whatsapp\_message.                                                                         |
    | `conversation_id`  | String   | Identifier of the WhatsApp conversation the message belongs to.                                                  |
    | `sent_at`          | Datetime | Instant (UTC) the message was sent, used as the incremental replication key.                                     |
    | `direction`        | String   | Whether the message was received (inbound) or sent (outbound).                                                   |
    | `author_phone`     | String   | E.164 phone of who wrote the message: the seller for outbound, the contact or group participant for inbound.     |
    | `author_name`      | String   | Display name of the author.                                                                                      |
    | `type`             | String   | Kind of message (text, image, video, audio, document, sticker, location, contact, poll, interactive or unknown). |
    | `text`             | String   | Message text or media caption, sanitized; null when absent or deleted.                                           |
    | `media_file_name`  | String   | File name of the attached media.                                                                                 |
    | `media_mime_type`  | String   | MIME type of the attached media.                                                                                 |
    | `media_size_bytes` | Integer  | Size of the attached media, in bytes.                                                                            |
    | `transcription`    | String   | Transcription of an audio message, sanitized, when one exists.                                                   |
    | `edited_at`        | Datetime | Instant (UTC) the author last edited the message; text is the current version.                                   |
    | `deleted_at`       | Datetime | Instant (UTC) the message was deleted; the row stays as a tombstone.                                             |
    | `deleted_reason`   | String   | Why the message was deleted (revoked\_for\_everyone, deleted\_locally or chat\_deleted), or null.                |
  </Accordion>
</AccordionGroup>
