> ## 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.

# Suri as a data source

> Bring data from Suri to Nekt.

[Suri](https://sejasuri.gitbook.io/manual-de-integracao) (formerly ChatbotMaker) is a Brazilian WhatsApp chatbot, CRM, and conversational commerce platform. This connector uses Suri's REST API to extract contacts, message templates, campaigns, conversational flows, human-attendance history, and Suri Shop catalog/order data.

<Note>
  Suri is multi-tenant: each customer chatbot has its own API root and access token, both found in the chatbot's Portal Settings.
</Note>

## Configuring Suri 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 Suri option from the list of connectors.

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

### 1. Add account access

Authentication uses a static **Bearer token**, unique per chatbot.

<Steps>
  <Step title="Open your chatbot's Portal Settings">
    In the Suri Portal, go to your chatbot's settings to find its API root URL (formatted like `https://xxx.azurewebsites.net/api`) and API token.
  </Step>

  <Step title="Paste the API URL and token into Nekt">
    Fill in the **Chatbot API URL** and **API Token** fields with the values from the previous step.
  </Step>
</Steps>

<Warning>
  The API Token grants full access to this chatbot's data (contacts, messages, orders). Keep it secret — never share it or commit it to public code.
</Warning>

The following configurations are available:

* **Chatbot API URL**: (Required) The chatbot's API root, e.g. `https://xxx.azurewebsites.net/api`.
* **API Token**: (Required) The static Bearer token from Portal Settings described above.
* **Start Date**: (Optional) Lower bound for the `shop_orders` and `attendances` streams. If omitted, defaults to 30 days before the current date.

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.

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**: you can choose between INCREMENTAL and FULL\_TABLE.
  * Incremental: every time the extraction happens, we'll get only the new data - which is good if, for example, you want to keep every record ever fetched.
  * Full table: every time the extraction happens, we'll get the current state of the data - which is good if, for example, you don't want to have deleted data in your catalog.

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.

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 Suri and their corresponding fields.

<AccordionGroup>
  <Accordion title="Departments">
    Departments the chatbot can route contacts to, from `/departments`. Full-table sync.

    **Key Fields:**

    | Field  | Type   | Description                     |
    | :----- | :----- | :------------------------------ |
    | `id`   | String | Unique identifier (primary key) |
    | `Name` | String | Department name                 |
  </Accordion>

  <Accordion title="Attendants">
    Human attendants (agents) registered on the chatbot, from `/attendants`. Full-table sync.

    **Key Fields:**

    | Field   | Type   | Description                     |
    | :------ | :----- | :------------------------------ |
    | `id`    | String | Unique identifier (primary key) |
    | `name`  | String | Attendant name                  |
    | `email` | String | Attendant email                 |
  </Accordion>

  <Accordion title="Channels">
    Communication channels connected to the chatbot (WhatsApp, Webchat, etc.), from `/channels`. Full-table sync.

    **Key Fields:**

    | Field      | Type    | Description                     |
    | :--------- | :------ | :------------------------------ |
    | `id`       | String  | Unique identifier (primary key) |
    | `name`     | String  | Channel name                    |
    | `provider` | Integer | Provider code                   |
    | `type`     | Integer | Channel type code               |
  </Accordion>

  <Accordion title="Attendance Reasons">
    Reasons attendants can select when closing an attendance, from `/attendances/reasons`. Full-table sync.

    **Key Fields:**

    | Field  | Type   | Description                     |
    | :----- | :----- | :------------------------------ |
    | `id`   | String | Unique identifier (primary key) |
    | `name` | String | Reason label                    |
  </Accordion>

  <Accordion title="Templates">
    WhatsApp/message templates registered on the chatbot, from `/templates`. Full-table sync.

    **Key Fields:**

    | Field                | Type    | Description                                   |
    | :------------------- | :------ | :-------------------------------------------- |
    | `id`                 | String  | Unique identifier (primary key)               |
    | `chatbotId`          | String  | Chatbot the template belongs to               |
    | `channelId`          | String  | Channel the template is registered on         |
    | `channelName`        | String  | Channel display name                          |
    | `messageId`          | String  | Submission id at the provider (e.g. Meta)     |
    | `title`              | String  | Template title/name                           |
    | `body`               | String  | Template body text, with `{{n}}` placeholders |
    | `status`             | Integer | Approval status code                          |
    | `rejectedReason`     | String  | Rejection reason, if any                      |
    | `isWhatsappTemplate` | Boolean | Whether it's a WhatsApp-approved template     |
    | `parameters`         | Integer | Number of `{{n}}` placeholders in the body    |
  </Accordion>

  <Accordion title="Campaigns">
    Bulk message campaigns sent from the chatbot, from `/campaigns`. Full-table sync.

    **Key Fields:**

    | Field                                                                                                       | Type              | Description                                        |
    | :---------------------------------------------------------------------------------------------------------- | :---------------- | :------------------------------------------------- |
    | `id`                                                                                                        | String            | Unique identifier (primary key)                    |
    | `chatbotId`                                                                                                 | String            | Chatbot the campaign belongs to                    |
    | `name`                                                                                                      | String            | Campaign name                                      |
    | `channelId`                                                                                                 | String            | Channel the campaign sends through                 |
    | `when`                                                                                                      | Datetime          | Scheduled send date/time                           |
    | `status`                                                                                                    | Integer           | Campaign status code                               |
    | `totalContacts`, `totalSent`, `totalDelivered`, `totalRead`, `totalErrors`, `totalAnswered`, `totalExpired` | Integer           | Campaign delivery counters                         |
    | `actions`                                                                                                   | Array             | Actions performed (e.g. which templates were sent) |
    | `dateCreate`, `dateStart`, `dateCancel`                                                                     | Datetime          | Lifecycle timestamps                               |
    | `response`                                                                                                  | Object            | How replies to the campaign are routed             |
    | `processingErrors`, `buttonsResponse`                                                                       | String (raw JSON) | Undocumented schema in the API reference           |
  </Accordion>

  <Accordion title="Flows">
    Conversational flows defined in the chatbot's Portal flow builder, from `/flows`. Full-table sync.

    **Key Fields:**

    | Field                                                 | Type              | Description                                                                                                                                                  |
    | :---------------------------------------------------- | :---------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `id`                                                  | String            | Unique identifier (primary key)                                                                                                                              |
    | `chatbotId`                                           | String            | Chatbot the flow belongs to                                                                                                                                  |
    | `name`                                                | String            | Flow name                                                                                                                                                    |
    | `fixed`                                               | Boolean           | Whether this is a built-in flow                                                                                                                              |
    | `version`                                             | Integer           | Flow version number                                                                                                                                          |
    | `trigger`, `actions`, `followUp`, `assistantBehavior` | String (raw JSON) | Trigger config and the flow's action tree — `actions` is polymorphic (discriminated by a C# `$type`), so it's kept as raw JSON rather than partially modeled |
  </Accordion>

  <Accordion title="Contacts">
    Chatbot contacts, listed via `POST /contacts/list` (the non-deprecated search endpoint). Full-table sync, paginated via `continuationToken`.

    **Key Fields:**

    | Field                                                                                | Type              | Description                                                                     |
    | :----------------------------------------------------------------------------------- | :---------------- | :------------------------------------------------------------------------------ |
    | `id`                                                                                 | String            | Unique identifier (primary key)                                                 |
    | `name`                                                                               | String            | Contact display name                                                            |
    | `phone`                                                                              | String            | Phone number (DDI+DDD+number)                                                   |
    | `email`                                                                              | String            | Contact email                                                                   |
    | `dateCreate`                                                                         | Datetime          | When the contact was created                                                    |
    | `lastActivity`                                                                       | Datetime          | When the contact last interacted                                                |
    | `tags`                                                                               | Array of String   | Tag identifiers currently applied                                               |
    | `userTags`                                                                           | Array of Object   | Tags with the date each was added                                               |
    | `agent_status`, `agent_departmentId`, `agent_platformUserId`, `agent_unreadMessages` | —                 | Flattened from the `agent` object: current attendance queue state               |
    | `session_id`, `session_type`, `session_start`, `session_end`                         | —                 | Flattened from the `session` object: current messaging session                  |
    | `currentDialog`, `variables`                                                         | String (raw JSON) | Current flow position and free-form per-account custom fields — no fixed schema |

    <Note>
      `POST /contacts/list` has no date filter, only sort order (`orderBy`/`orderType`) — so there's no way to ask the API for "only contacts changed since X". This stream does a full sync every run.
    </Note>
  </Accordion>

  <Accordion title="Attendances">
    Human attendance history, from `POST /attendances`. Incremental sync on `startDate`.

    **Key Fields:**

    | Field                                              | Type              | Description                                                    |
    | :------------------------------------------------- | :---------------- | :------------------------------------------------------------- |
    | `protocol`                                         | String            | Unique protocol number (primary key)                           |
    | `status`                                           | Integer           | Attendance status code                                         |
    | `startDate`, `endDate`, `requestDate`              | Datetime          | Attendance lifecycle timestamps (replication key: `startDate`) |
    | `attendantId`, `attendantName`                     | String            | Attendant who handled the attendance                           |
    | `departmentId`, `departmentName`                   | String            | Department the attendance was routed to                        |
    | `waitingTime`, `attendanceTime`, `avgResponseTime` | Number            | Timing metrics                                                 |
    | `reasonId`, `reason`                               | String            | Attendance reason selected when closing                        |
    | `user_id`, `user_name`, `user_email`, `user_phone` | —                 | Flattened contact info for this attendance                     |
    | `order`                                            | String (raw JSON) | Order tied to this attendance, if any — undocumented schema    |

    <Note>
      `POST /attendances` requires an explicit `startDate`/`endDate` window (format `yyyy-MM-dd`) on every call. The API reference doesn't document pagination for it, so each sync issues one request covering `[bookmark or start_date or 30 days ago, today]`.
    </Note>
  </Accordion>

  <Accordion title="Shop Categories">
    Product categories in the Suri Shop catalog, from `/shop/categories`. Full-table sync.

    **Key Fields:**

    | Field         | Type              | Description                      |
    | :------------ | :---------------- | :------------------------------- |
    | `id`          | String            | Unique identifier (primary key)  |
    | `name`        | String            | Category name                    |
    | `description` | String            | Category description             |
    | `children`    | String (raw JSON) | Recursively nested subcategories |
  </Accordion>

  <Accordion title="Shop Stores">
    Physical/logistic stores in the Suri Shop catalog, from `/shop/stores`. Full-table sync.

    **Key Fields:**

    | Field                   | Type              | Description                                                    |
    | :---------------------- | :---------------- | :------------------------------------------------------------- |
    | `id`                    | String            | Unique identifier (primary key)                                |
    | `name`                  | String            | Store name                                                     |
    | `fullAddress`           | Object            | Structured store address (state, city, street, zip code, etc.) |
    | `address`, `serviceTax` | String (raw JSON) | Observed as null in every sample response; undocumented schema |
  </Accordion>

  <Accordion title="Shop Collections">
    Curated product collections in the Suri Shop catalog, from `/shop/collections`. Full-table sync.

    **Key Fields:**

    | Field        | Type            | Description                                    |
    | :----------- | :-------------- | :--------------------------------------------- |
    | `id`         | String          | Unique identifier (primary key)                |
    | `providerId` | String          | Identifier at the source provider              |
    | `name`       | String          | Collection name                                |
    | `shopId`     | String          | Shop the collection belongs to                 |
    | `products`   | Array of String | Provider IDs of the products in the collection |
  </Accordion>

  <Accordion title="Shop Products">
    Products in the Suri Shop catalog, from `POST /shop/products/list`. Full-table sync, paginated via a `pageToken` cursor.

    **Key Fields:**

    | Field                       | Type              | Description                                                                                                                                               |
    | :-------------------------- | :---------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `id`                        | String            | Unique identifier (primary key)                                                                                                                           |
    | `sku`                       | String            | Base SKU                                                                                                                                                  |
    | `categoryId`                | String            | Category the product belongs to                                                                                                                           |
    | `name`, `description`       | String            | Product name and description                                                                                                                              |
    | `price`, `promotionalPrice` | Number            | Pricing                                                                                                                                                   |
    | `isActive`                  | Boolean           | Whether the product is active/visible                                                                                                                     |
    | `images`                    | Array of Object   | Product images                                                                                                                                            |
    | `attributes`                | Array of Object   | Variant-defining attributes (e.g. color, size) and their values                                                                                           |
    | `dimensions`                | String (raw JSON) | Product variants (SKU, per-attribute value, price, per-store stock) — kept as raw JSON since the attribute names and store ids inside it vary per product |
  </Accordion>

  <Accordion title="Shop Orders">
    Orders placed through the Suri Shop, from `POST /shop/orders`. Incremental sync on `createdDate`, paginated by page number.

    **Key Fields:**

    | Field                                                                                                                 | Type              | Description                                                                                                          |
    | :-------------------------------------------------------------------------------------------------------------------- | :---------------- | :------------------------------------------------------------------------------------------------------------------- |
    | `id`                                                                                                                  | String            | Unique identifier (primary key)                                                                                      |
    | `status`                                                                                                              | Integer           | Order status code (0 Creating, 1 Received, 2 Paid, 3 Cancelled, 4 Error)                                             |
    | `createdDate`                                                                                                         | Datetime          | When the order was created (replication key)                                                                         |
    | `receivedDate`, `finalizedDate`, `canceledDate`                                                                       | Datetime          | Order lifecycle timestamps                                                                                           |
    | `itemsAmount`, `feeAmount`, `discountAmount`, `totalAmount`                                                           | Number            | Order totals                                                                                                         |
    | `hasAssistance`, `isRebuy`, `isExternalOrder`, `isRecoveredOrder`                                                     | Boolean           | Order flags                                                                                                          |
    | `satisfactionSurvey`                                                                                                  | Object            | Post-order satisfaction survey response                                                                              |
    | `seller`, `customer`, `logistic`, `payment`, `coupon`, `items`, `platformUser`, `errorMessages`, `origin`, `referral` | String (raw JSON) | Observed as null/empty in every sample response, with no field-level docs — kept as raw JSON pending real order data |

    <Note>
      `CreatedDate` bounds the window server-side (undocumented default: last 30 days) and is used as both the replication key and the incremental filter — this only catches new orders, not status changes to orders created before the current bookmark window.
    </Note>
  </Accordion>
</AccordionGroup>

## Implementation Notes

### Sync mode

`shop_orders` and `attendances` sync incrementally. All other streams are full-table syncs.

### Pagination

Suri's simple `GET` list endpoints (departments, attendants, channels, templates, campaigns, flows, attendance reasons, shop categories/stores/collections) return their full result set in one response — every example in the API reference does, and no page/limit params are documented for them.

The `POST`-based list/search endpoints paginate differently from each other:

* `contacts`: cursor via `continuationToken`, echoed back in the request body.
* `shop_products`: cursor via `pageToken` + a `hasMore` flag, both under `data`.
* `shop_orders`: page number (`Page`/`PerPage` in the request body) + a `hasMore` flag under `data`.

### API limitations / undocumented behavior

This V1 was built entirely from the public [API reference](https://documenter.getpostman.com/view/17684221/UUxz9mt5) — Nekt does not yet have access to the requesting customer's Suri account to validate against real data. Known gaps:

* `contacts` has no server-side date filter, so it's a full sync every run (see the Contacts note above).
* Several nested fields have no documented schema and were always null/empty in every sample response: `shop_orders.seller/customer/logistic/payment/items/platformUser/errorMessages/origin/referral`, `flows.actions/trigger`, and `shop_products.dimensions`'s inner variant/stock shape. These are kept as raw JSON strings.
* The "get by id" endpoints (contact, template, campaign, category, product, order, collection, flow, attendance reason by id) and `GET /contacts/:user_id/messages` exist in the API but aren't included in V1 — they need an id from a parent stream and largely duplicate data already present in the corresponding list endpoint.
* Write/action endpoints (import contact, send message, create/update/delete category/product/collection/order actions, webhook registration) are out of scope for an extractor.

## Skills for agents

<Snippet file="agent-skills-intro.mdx" />

<Card title="Download Suri skills file" icon="wand-magic-sparkles" href="/sources/suri.md">
  Suri connector documentation as plain markdown, for use in AI agent contexts.
</Card>
