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

# SugarCRM as a data source

> Bring every SugarCRM module (accounts, contacts, leads, opportunities, cases, activities, quotes, custom modules and custom fields) to Nekt.

SugarCRM is a CRM platform for sales, marketing, and customer service (Sugar Sell, Sugar Serve, Sugar Enterprise, and Sugar Professional), available in SugarCRM's cloud or installed on your own servers. This connector reads your instance through the official SugarCRM REST API and brings one table per module: accounts, contacts, leads, opportunities, cases, calls, meetings, tasks, notes, quotes, products, your custom modules, and everything else the connector's user can list, with all their fields, custom fields included.

> [!NOTE]
>
> The connector only reads data. It never creates, changes, or deletes anything in SugarCRM.

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

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

### 1. Prepare SugarCRM

The SugarCRM API always acts as a SugarCRM user and sees exactly what that user's role allows. Before you add the source:

**1. Choose the user**

We recommend a user dedicated to this integration, with a role that has **Access** and **List** rights on every module you want to sync. The user must log in with a SugarCRM password: users that only sign in through single sign-on (SAML, Google, Microsoft) cannot be used by the API.

**2. Register the API platform**

A SugarCRM administrator opens **Admin > Configure API Platforms**, adds a platform named `nekt`, and clicks **Save**. The connector logs in on this platform so it does not end the user's SugarCRM web session.

> [!WARNING]
>
> SugarCRM keeps one session per user per platform. If you cannot register the `nekt` platform, set **API Platform** to `base`, but then use a user nobody logs in with: on `base`, every sync logs that user out of SugarCRM, and a person logging in with that user interrupts the sync.

### 2. Add account access

* **Instance URL**: the address you open SugarCRM with, for example `https://yourcompany.sugarondemand.com`. It must start with `https://`.
* **User Name** and **Password**: the SugarCRM user chosen above.
* **API Platform** (default `nekt`): the platform registered above, or `base`.
* **Start Date** (optional): only records modified since this date are loaded on the first sync and on full syncs. Leave it empty to load every record. Modules without a modification date are always loaded whole.

> [!TIP]
>
> On large SugarCRM instances, set a Start Date. A first sync without it reads every record of every selected module, and if it stops halfway the next sync starts it over from the beginning.

Advanced settings, which you normally keep as they are:

* **OAuth Client ID** (default `sugar`) and **OAuth Client Secret** (empty): the OAuth key the connector logs in with. `sugar` exists on every SugarCRM instance; use another pair only if your administrator created one under **Admin > OAuth Keys**.
* **API Version** (default `v11_4`): the SugarCRM REST API version. Works on SugarCRM 9 and later; older installations may need `v11` or `v10`.
* **Page Size** (default 200): records read per request. Lower it if SugarCRM times out on modules with many fields.

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

### 3. Select streams

The connector lists one stream per SugarCRM module the user can access, so the list depends on your instance and on the user's role. For faster extractions, select only the modules that are relevant to your analysis.

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

Select the streams and click **Next**.

### 4. 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**: keep the suggested type. Modules with a modification date (almost all of them) are **Incremental**: each sync reads only the records changed since the previous one and merges them into the table. Modules without it are **Full table**: each sync reads them whole and replaces the table.

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

### 5. 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/runs/scheduling-and-triggers.md), 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). Records are read incrementally, so an hourly or daily sync works well.

Optionally, you can 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).

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

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

# Streams and Fields

## Available streams

Each SugarCRM module becomes one stream, named after the module in lowercase with underscores (`Accounts` becomes `accounts`, `RevenueLineItems` becomes `revenue_line_items`, a custom module `abc_Projects` becomes `abc_projects`). The slug is the exact identifier to pass when creating the source via API. Every stream has the primary key `id`.

The most common modules are listed below. Which ones exist depends on your SugarCRM edition, your configuration, and the user's role.

| Stream | Slug | Sync | Description |
| - | - | - | - |
| Accounts | `accounts` | Incremental | Companies and organizations you do business with. |
| Contacts | `contacts` | Incremental | People, usually linked to an account. |
| Leads | `leads` | Incremental | Prospects not yet converted to contacts. |
| Opportunities | `opportunities` | Incremental | Sales deals, with amount, stage, and expected close date. |
| Revenue Line Items | `revenue_line_items` | Incremental | Products or services of an opportunity (Sugar Sell and Enterprise). |
| Cases | `cases` | Incremental | Customer support cases. |
| Calls | `calls` | Incremental | Logged and scheduled calls. |
| Meetings | `meetings` | Incremental | Logged and scheduled meetings. |
| Tasks | `tasks` | Incremental | Tasks and to-dos. |
| Notes | `notes` | Incremental | Notes and attachment records. |
| Emails | `emails` | Incremental | Archived and sent emails. |
| Campaigns | `campaigns` | Incremental | Marketing campaigns. |
| Quotes | `quotes` | Incremental | Quotes sent to customers. |
| Products | `products` | Incremental | Quoted line items. |
| Product Templates | `product_templates` | Incremental | The product catalog. |
| Documents | `documents` | Incremental | Document records. |
| Bugs | `bugs` | Incremental | Bug tracker records. |
| Knowledge Base | `kb_contents` | Incremental | Knowledge base articles. |
| Users | `users` | Incremental | SugarCRM users (no passwords). |
| Teams | `teams` | Incremental | Teams used for record visibility. |
| Currencies | `currencies` | Full table | Currencies and conversion rates. |
| Custom modules | lowercase module name | Incremental | Modules created in Studio or Module Builder. |

Modules that hold no business records or hold credentials are not offered: Home, Calendar, the activity stream, administration and configuration modules, OAuth keys and tokens, email account settings, schedulers, trackers, user preferences, and forecast worksheets.

Records link to each other through their `*_id` fields: for example `contacts.account_id`, `opportunities.account_id`, `cases.account_id`, and `assigned_user_id` = `users.id` in every module. Activities (calls, meetings, tasks, notes) point to their record with `parent_type` (the module) and `parent_id`.

## Fields by stream

Each table has a column for every field of its module that SugarCRM stores, including custom fields (their names end in `_c`), plus a few computed fields that are useful as they are: the names of related records (for example `account_name` and `assigned_user_name`), the email addresses of people and companies, teams, and tags. Relationship links and password fields are not loaded. Columns are named like the SugarCRM fields. Dates and times are in UTC. Fields marked String (JSON) hold a list as JSON text; use your warehouse's JSON functions to read them.

> [accordion] Fields of every module
>
> Table: one per module · Primary key: `id` · Sync: Incremental (`date_modified`), or Full table for modules without it
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `id` | String | Unique identifier of the record. |
> | `name` | String | Name of the record (for people, the full name). |
> | `date_entered` | Datetime | When the record was created (UTC). |
> | `date_modified` | Datetime | When the record was last modified (UTC); used as the incremental replication key. |
> | `modified_user_id` | String | Id of the user who last modified the record. |
> | `created_by` | String | Id of the user who created the record. |
> | `description` | String | Description of the record. |
> | `deleted` | Boolean | Deletion flag; always false, because SugarCRM does not list deleted records. |
> | `assigned_user_id` | String | Id of the user the record is assigned to (see `users.id`). |
> | `assigned_user_name` | String | Name of that user. |
> | `team_id` | String | Id of the record's main team. |
> | `team_set_id` | String | Id of the set of teams that can see the record. |
> | `tag` | String (JSON) | Tags of the record. |
> | `*_c` | Varies | Custom fields, typed by their SugarCRM field type. |

> [accordion] Field types
>
> | SugarCRM field type | Column type |
> | :- | :- |
> | Text, text area, dropdown, URL, phone, relate, ID | String |
> | Integer | Integer |
> | Decimal, currency, float | Number (exact decimals) |
> | Checkbox | Boolean |
> | Datetime | Datetime (UTC) |
> | Date | Date |
> | Multiselect, email addresses, teams, tags | String (JSON) |

> [accordion] Accounts
>
> Table: `accounts` · Primary key: `id` · Sync: Incremental (`date_modified`)
>
> Typical standard fields, in addition to the fields of every module:
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `account_type` | String | Type of account (customer, partner, prospect...). |
> | `industry` | String | Industry of the account. |
> | `annual_revenue` | String | Annual revenue, as entered. |
> | `employees` | String | Number of employees, as entered. |
> | `rating` | String | Rating of the account. |
> | `ownership` | String | Ownership of the account. |
> | `phone_office` | String | Main phone number. |
> | `phone_alternate` | String | Alternate phone number. |
> | `website` | String | Website address. |
> | `billing_address_street`, `billing_address_city`, `billing_address_state`, `billing_address_postalcode`, `billing_address_country` | String | Billing address. |
> | `shipping_address_street`, `shipping_address_city`, `shipping_address_state`, `shipping_address_postalcode`, `shipping_address_country` | String | Shipping address. |
> | `parent_id` | String | Id of the parent account. |
> | `campaign_id` | String | Id of the campaign that generated the account. |
> | `email` | String (JSON) | Email addresses of the account, with the primary, opted-out, and invalid flags. |

> [accordion] Contacts and Leads
>
> Tables: `contacts`, `leads` · Primary key: `id` · Sync: Incremental (`date_modified`)
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `salutation`, `first_name`, `last_name` | String | Name of the person. |
> | `title` | String | Job title. |
> | `department` | String | Department. |
> | `phone_work`, `phone_mobile`, `phone_home`, `phone_other`, `phone_fax` | String | Phone numbers. |
> | `primary_address_street`, `primary_address_city`, `primary_address_state`, `primary_address_postalcode`, `primary_address_country` | String | Primary address. |
> | `lead_source` | String | Where the person came from. |
> | `account_id`, `account_name` | String | Account of the contact (contacts). |
> | `account_name` | String | Company name typed on the lead (leads). |
> | `status` | String | Status of the lead (leads). |
> | `converted` | Boolean | Whether the lead was converted (leads). |
> | `contact_id` | String | Contact created from the lead (leads). |
> | `do_not_call` | Boolean | Whether the person must not be called. |
> | `email` | String (JSON) | Email addresses of the person, with the primary, opted-out, and invalid flags. |

> [accordion] Opportunities
>
> Table: `opportunities` · Primary key: `id` · Sync: Incremental (`date_modified`)
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `account_id`, `account_name` | String | Account of the opportunity. |
> | `amount` | Number | Amount in the opportunity's currency. |
> | `amount_usdollar` | Number | Amount in the system currency. |
> | `currency_id` | String | Currency of the amount (see `currencies.id`). |
> | `date_closed` | Date | Expected close date. |
> | `sales_stage` | String | Sales stage. |
> | `sales_status` | String | Sales status (Sugar Sell and Enterprise). |
> | `probability` | Integer | Probability of closing, in percent. |
> | `opportunity_type` | String | Type of opportunity. |
> | `lead_source` | String | Where the opportunity came from. |
> | `next_step` | String | Next step. |
> | `campaign_id` | String | Campaign of the opportunity. |

> [accordion] Cases
>
> Table: `cases` · Primary key: `id` · Sync: Incremental (`date_modified`)
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `case_number` | Integer | Case number. |
> | `type` | String | Type of case. |
> | `status` | String | Status of the case. |
> | `priority` | String | Priority. |
> | `resolution` | String | Resolution text. |
> | `account_id`, `account_name` | String | Account of the case. |
> | `source` | String | Channel the case came from. |
> | `follow_up_datetime` | Datetime | Follow-up date (UTC, Sugar Serve). |

> [accordion] Calls, Meetings, and Tasks
>
> Tables: `calls`, `meetings`, `tasks` · Primary key: `id` · Sync: Incremental (`date_modified`)
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `status` | String | Status (planned, held, not held; tasks: not started, in progress, completed...). |
> | `direction` | String | Inbound or outbound (calls). |
> | `date_start` | Datetime | Start (UTC). |
> | `date_end` | Datetime | End (UTC, calls and meetings). |
> | `date_due` | Datetime | Due date (UTC, tasks). |
> | `duration_hours`, `duration_minutes` | Integer | Duration (calls and meetings). |
> | `location` | String | Location (meetings). |
> | `priority` | String | Priority (tasks). |
> | `parent_type` | String | Module of the related record (Accounts, Contacts, Opportunities...). |
> | `parent_id` | String | Id of the related record. |
> | `contact_id` | String | Contact of the task (tasks). |

## Implementation Notes

### Data Quality Considerations

* **What the user sees is what you get.** The connector reads as the configured user. Modules the user's role cannot list are not offered or, if access is removed later, show as failed with a message saying so while the other tables keep syncing. Fields hidden by field-level security come empty.
* **How tables stay up to date.** SugarCRM updates a record's `date_modified` whenever it changes. Each sync reads the records modified since the previous one, starting 10 minutes earlier to cover saves that finish late, and merges them into the table. A record edited while a sync runs is read again with its newest version.
* **Names of related records and email addresses.** Columns such as `account_name`, `assigned_user_name`, `parent_name`, and `email` are filled by SugarCRM from the related record when the record is read. Renaming an account or a user, or changing an email address's opt-out or invalid flag, does not change the modification date of the records that point to it, so Incremental tables keep the value as of each record's last modification. For the current value, join on the `*_id` fields (`account_id`, `assigned_user_id`, `parent_id`) with the related table, or run a full sync periodically.
* **Deleted records.** SugarCRM does not list deleted records. A record deleted in SugarCRM stays in an Incremental table as it was last loaded; run a full sync of the source to remove it. Full table tables drop it on the next sync.
* **Relationships between modules.** Many-to-many relationship tables (for example, which contacts take part in which opportunities) are not modules and are not loaded. One-to-many links are in the `*_id` fields of each record.
* **New fields.** A field added in SugarCRM appears in the table after you refresh the stream's columns in Nekt. A field deleted or renamed in SugarCRM comes empty, and the sync log names it.
* **Values that do not fit their type.** A value that cannot be read as its column type (for example, letters in an integer field) is loaded empty, and the sync log says how many values in which columns.
* **Full table tables are never half updated.** The connector reads all the data of a full table table before writing any of it. If SugarCRM fails while it is read, nothing of that table is sent and the sync shows it as failed.

### API Limits & Performance

* SugarCRM does not document a request limit for its REST API. When an instance asks the connector to slow down, it waits and tells you in the sync log.
* Records are read 200 per request by default, one request at a time. Modules with many fields or very long texts (such as emails) take longer per record.
* The list of modules and fields is read when you set up or edit the source. Each sync only reads the definitions of the selected modules.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.