<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://sugarclub.sugarai.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Integrations for Product Devs</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs</link><description /><dc:language>en-US</dc:language><generator>Telligent Community 12</generator><item><title>Integrations for Product Devs</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs</link><pubDate>Wed, 10 Sep 2025 15:09:30 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:e64c91c4-03e5-454f-bbd7-3beb25519ac3</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs#comments</comments><description>Current Revision posted to Dev Tutorials by Rafael Fernandes on 9/10/2025 3:09:30 PM&lt;br /&gt;
&lt;table style="margin-left:auto;margin-right:auto;width:100%;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#approach"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#rest"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#common"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#performance"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="approach"&gt;&lt;/a&gt;Integration Approaches&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;The Sugar platform is extremely powerful, flexible, and allows for easy integration. This flexibility means that determining the&amp;nbsp;best approach for your use case scenario is the key to success.&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Push/Pull from Sugar via REST API&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="text-decoration:underline;"&gt;Recommended&lt;/span&gt; approach&lt;/li&gt;
&lt;li&gt;Developers have full control over integration&lt;/li&gt;
&lt;li&gt;Integration can be stopped and systems will continue to work&lt;/li&gt;
&lt;li&gt;Retry mechanism: Resume integrations at any time (identify deltas through &amp;quot;last_update_time&amp;quot; flags)&lt;/li&gt;
&lt;li&gt;The time delay from/to Sugar is minimal&lt;/li&gt;
&lt;li&gt;Sugar REST API offers almost everything you need,&amp;nbsp;and can be further extended via customization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push to Sugar, Sugar pushes to an external queue in realtime&lt;span&gt;&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar Events to trigger through Logic Hooks&lt;/li&gt;
&lt;li&gt;Requires&amp;nbsp;Logic Hooks (code customization) to be created and deployed&lt;/li&gt;
&lt;li&gt;Does not offer a &amp;quot;retry mechanism&amp;quot;, if a logic hook fails to deliver to a queue or contact an external system&lt;/li&gt;
&lt;li&gt;Synchronous in nature, requires a response from an external system&lt;/li&gt;
&lt;li&gt;Needs to handle dependencies manually (contact can only be created after account)&lt;/li&gt;
&lt;li&gt;Good to have a middleware/queue in front of Sugar to receive those event triggers to&amp;nbsp;reliably&amp;nbsp;manage peak loads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Realtime: Embed your app into Sugar&amp;nbsp;through &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/User_Interface/Dashlets/"&gt;Dashlets&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Simplest approach&lt;/li&gt;
&lt;li&gt;Often requires web user-based authentication&lt;/li&gt;
&lt;li&gt;All load/traffic goes directly to your system,&amp;nbsp;which makes your system the performance bottleneck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="rest"&gt;&lt;/a&gt;REST API Webservices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;Accessing your data when you want is good. Accessing your data however you want is better. &lt;/span&gt;&lt;span&gt;When you decide to build an integration with Sugar, you&amp;rsquo;ll need an easy way to access and interact with the data stored in Sugar. The REST (&lt;/span&gt;&lt;span&gt;representational state transfer)&lt;/span&gt;&lt;span&gt;&amp;nbsp;API (application programming interface) is perfect for this.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;You can also leverage our&amp;nbsp;live&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://rest.apidocs.sugarcrm.com/"&gt;Sugar RESTful API Collection&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sugar REST API Overview
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Fully RESTfull (GET, POST, PUT, DELETE)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;OAuth2 token based&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;All fields and modules are available through the API automatically&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Metadata API provides everything you need to know about your Sugar instance.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Topics
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/new-tutorial-intro-to-the-sugar-rest-api"&gt;Intro to the Sugar REST API&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/how-sugar-rest-api-versioning-works"&gt;How Sugar REST API versioning works&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/"&gt;RestAPI Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/sugarcrm-cookbook---the-school-of-rest---part-1"&gt;SugarCRM Cookbook - The School of REST - Part 1&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/"&gt;REST APIs Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Extending_Endpoints/"&gt;How to add your own custom endpoints to the REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/API_Exceptions/"&gt;API Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Best_Practices/"&gt;Best practices when integrating and migrating Sugar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="common"&gt;&lt;/a&gt;Common&amp;nbsp;APIs&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;It is important to understand our most commonly used APIs and their functions within Sugar. Your integration might need data within Sugar&amp;#39;s module structure that could potentially change over time, so you can use Metadata for it as well as CRUD onto Sugar.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Metadata
&lt;ul&gt;
&lt;li&gt;Endpoint with current system&amp;#39;s structure&lt;/li&gt;
&lt;li&gt;Modules, fields, relationships, layouts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Use carefully, its payload can be MBs in size, cache as much as possible&lt;/li&gt;
&lt;li&gt;GET /metadata (use filters as much as possible)&lt;/li&gt;
&lt;li&gt;It does not retrieve labels for dropdowns, use language API to do so&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/3-tips-for-using-the-sugar-metadata-api"&gt;3 Tips for using the Sugar Metadata API&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Language
&lt;ul&gt;
&lt;li&gt;Endpoint to retrieve labels&lt;/li&gt;
&lt;li&gt;Dropdown list values&lt;/li&gt;
&lt;li&gt;Any language-specific content&lt;/li&gt;
&lt;li&gt;GET /lang/&amp;lt;language_code&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;CRUD (Create, Read, Update, Delete) records&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_GET"&gt;Read&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/module_POST"&gt;Create&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;POST /&amp;lt;module&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_PUT"&gt;Update&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;PUT&amp;nbsp;&lt;span&gt;/&amp;lt;module&amp;gt;/:record&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_DELETE"&gt;Delete&lt;/a&gt;:&amp;nbsp;&lt;code&gt;DELETE&amp;nbsp;/&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulefilter_POST"&gt;Filter&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;POST /&amp;lt;module&amp;gt;/filter&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;You can use&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulefilter_GET"&gt;GET&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;as well&lt;/li&gt;
&lt;li&gt;POST solves the issue when a query is too long and hits HTTP limits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecordlinklink_name_GET"&gt;Retrieve records related to another module&lt;/a&gt;:&amp;nbsp;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record/link/:link_name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecordlinklink_nameremote_id_POST"&gt;Creates a relationship to a pre-existing record:&lt;/a&gt;&lt;code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;POST /&amp;lt;module&amp;gt;/:record/link/:link_name/:remote_id&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="performance"&gt;&lt;/a&gt;Performance and Best Practices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/h1&gt;
&lt;div class="row"&gt;
&lt;div class="col-xs-12 col-md-9"&gt;
&lt;p&gt;As you deep dive into Sugar APIs,&amp;nbsp;you will see how easy it is to integrate to pull and push data from and to Sugar and your systems, however, you must consider performance so your integration doesn&amp;#39;t become a bottleneck between those systems.&lt;/p&gt;
&lt;p&gt;You should consider the following guidelines when implementing your integrations:&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar&amp;#39;s sync_key to link to remote IDs
&lt;ul&gt;
&lt;li&gt;Sugar provides in every module a sync_key field&lt;/li&gt;
&lt;li&gt;sync_key is a unique identifier for that module that links back to your external system&amp;#39;s generated key&lt;/li&gt;
&lt;li&gt;For example, account ID from ERP is AC0001, set sync_key (pass as a parameter in the POST) and sugar will create a record in account with sync_key=AC0001&lt;/li&gt;
&lt;li&gt;Next patch/update, sugar will check &amp;quot;where sync_key=&amp;#39;AC0001&amp;#39;&amp;quot; and update it (it is indexed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Integrate Upsert APIs
&lt;ul&gt;
&lt;li&gt;Sugar&amp;#39;s &amp;quot;update or insert&amp;quot; API based on sync_key&lt;/li&gt;
&lt;li&gt;Simplifies a common operation - if record exists, update it, otherwise create it (GET followed by a&amp;nbsp;PUT or POST)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_PATCH"&gt;Upsert by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_GET"&gt;Get by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_DELETE"&gt;Delete by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulerecord_idsync_key_field_namesync_key_field_value_PATCH"&gt;Set a sync on existing record (without sync_key)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_POST"&gt;Create relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_DELETE"&gt;Delete relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong data-start="1409" data-end="1418"&gt;Note:&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;This endpoint is engineered for maximum performance and omits several ACL and validation checks.&lt;/li&gt;
&lt;li&gt;&lt;strong data-start="1522" data-end="1536"&gt;Important:&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;For security reasons, the Upsert API is&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong data-start="1577" data-end="1611"&gt;restricted to Admin users only&lt;/strong&gt;&amp;mdash;non-admin users will be denied access.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Bulk API
&lt;ul&gt;
&lt;li&gt;An endpoint that encapsulates multiple API calls into one single HTTP request&lt;/li&gt;
&lt;li&gt;Requests are executed synchronously (one after the other)&lt;/li&gt;
&lt;li&gt;Reducing network latency between calls&lt;/li&gt;
&lt;li&gt;Combined with Upsert provides the best performance&lt;/li&gt;
&lt;li&gt;Careful not to add too many requests to it&lt;/li&gt;
&lt;li&gt;Start small (5 to 10 requests) and increase until you reach its max capacity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Polling and filtering time-based with Filter API
&lt;ul&gt;
&lt;li&gt;Integration gateway (or your external system) asks Sugar every X minutes&lt;/li&gt;
&lt;li&gt;Request Filter API using &lt;code&gt;max_num&lt;/code&gt; (max number of records), offset and fields&lt;/li&gt;
&lt;li&gt;The response will provide the data as well as &lt;code&gt;next_offset&lt;/code&gt; (offset can be seen as pagination)&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;next_offset&lt;/code&gt; is -1, no more records to go through&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Initial Data Load into Sugar&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Use Bulk + Upsert to achieve data loads&lt;/li&gt;
&lt;li&gt;Millions&amp;nbsp;of records may take a little while to process, plan ahead (over the weekend)&lt;/li&gt;
&lt;li&gt;Use multi-thread processes to load (for example 20 threads sending 20 bulk upsert requests)&lt;/li&gt;
&lt;li&gt;Careful with&amp;nbsp;&lt;a href="https://support.sugarcrm.com/Resources/Sugar_Cloud_Policy_Guide/#Rate_Limits"&gt;Sugar Cloud rate limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&amp;#39;s always a good idea to let Sugar Support know you&amp;#39;re data loading, they will be considerate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Understanding PHP limitations&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;PHP is single-threaded with limited resources to process your request&lt;/li&gt;
&lt;li&gt;If you send too much data using bulk, you may run out of memory for that request&lt;/li&gt;
&lt;li&gt;Push to the limits but give some room for PHP to finish the request gracefully&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Pagination for millions of records by using OFFSET will degrade performance
&lt;ul&gt;
&lt;li&gt;We rely on DB to find, sort and limit records&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/swlh/sql-pagination-you-are-probably-doing-it-wrong-d0f2719cc166"&gt;Nice article &lt;/a&gt;explaining how this works in details&lt;/li&gt;
&lt;li&gt;Instead of offsets, store the last processed ID and use it in the WHERE clause and sort by ID&lt;/li&gt;
&lt;li&gt;Example
&lt;ul&gt;
&lt;li&gt;Instead of: (/v11_25/Leads?max_num=1000&amp;amp;&lt;strong&gt;offset=4619000&lt;/strong&gt;&amp;amp;order_by=id)&lt;/li&gt;
&lt;li&gt;Do this&amp;nbsp;(/v11_25/Leads?&lt;strong&gt;filter=[{"id": {"$gt": &amp;rdquo;&amp;lt;last_id&amp;gt;"}}]&lt;/strong&gt;&amp;amp;max_num=1000&amp;amp;order_by=id)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If you need to add a date, make sure to add it as part of the filter and order&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p id="mcetoc_1f5uvkqns0"&gt;&lt;span style="font-size:150%;"&gt;You&amp;#39;re up and running, but don&amp;#39;t stop now - this is just the beginning of your journey. &lt;/span&gt;&lt;/p&gt;
&lt;p id="mcetoc_1g9jl704d0"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Now it&amp;#39;s time for&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/676/customization-for-product-devs"&gt;Customization for Product Devs&lt;/a&gt;.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Integrations for Product Devs</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs/revision/12</link><pubDate>Thu, 14 Aug 2025 17:26:46 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:e64c91c4-03e5-454f-bbd7-3beb25519ac3</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs#comments</comments><description>Revision 12 posted to Dev Tutorials by Rafael Fernandes on 8/14/2025 5:26:46 PM&lt;br /&gt;
&lt;table style="margin-left:auto;margin-right:auto;width:100%;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#approach"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#rest"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#common"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#performance"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="approach"&gt;&lt;/a&gt;Integration Approaches&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;The Sugar platform is extremely powerful, flexible, and allows for easy integration. This flexibility means that determining the&amp;nbsp;best approach for your use case scenario is the key to success.&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Push/Pull from Sugar via REST API&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="text-decoration:underline;"&gt;Recommended&lt;/span&gt; approach&lt;/li&gt;
&lt;li&gt;Developers have full control over integration&lt;/li&gt;
&lt;li&gt;Integration can be stopped and systems will continue to work&lt;/li&gt;
&lt;li&gt;Retry mechanism: Resume integrations at any time (identify deltas through &amp;quot;last_update_time&amp;quot; flags)&lt;/li&gt;
&lt;li&gt;The time delay from/to Sugar is minimal&lt;/li&gt;
&lt;li&gt;Sugar REST API offers almost everything you need,&amp;nbsp;and can be further extended via customization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push to Sugar, Sugar pushes to an external queue in realtime&lt;span&gt;&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar Events to trigger through Logic Hooks&lt;/li&gt;
&lt;li&gt;Requires&amp;nbsp;Logic Hooks (code customization) to be created and deployed&lt;/li&gt;
&lt;li&gt;Does not offer a &amp;quot;retry mechanism&amp;quot;, if a logic hook fails to deliver to a queue or contact an external system&lt;/li&gt;
&lt;li&gt;Synchronous in nature, requires a response from an external system&lt;/li&gt;
&lt;li&gt;Needs to handle dependencies manually (contact can only be created after account)&lt;/li&gt;
&lt;li&gt;Good to have a middleware/queue in front of Sugar to receive those event triggers to&amp;nbsp;reliably&amp;nbsp;manage peak loads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Realtime: Embed your app into Sugar&amp;nbsp;through &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/User_Interface/Dashlets/"&gt;Dashlets&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Simplest approach&lt;/li&gt;
&lt;li&gt;Often requires web user-based authentication&lt;/li&gt;
&lt;li&gt;All load/traffic goes directly to your system,&amp;nbsp;which makes your system the performance bottleneck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="rest"&gt;&lt;/a&gt;REST API Webservices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;Accessing your data when you want is good. Accessing your data however you want is better. &lt;/span&gt;&lt;span&gt;When you decide to build an integration with Sugar, you&amp;rsquo;ll need an easy way to access and interact with the data stored in Sugar. The REST (&lt;/span&gt;&lt;span&gt;representational state transfer)&lt;/span&gt;&lt;span&gt;&amp;nbsp;API (application programming interface) is perfect for this.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;You can also leverage our&amp;nbsp;live&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://rest.apidocs.sugarcrm.com/"&gt;Sugar RESTful API Collection&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sugar REST API Overview
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Fully RESTfull (GET, POST, PUT, DELETE)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;OAuth2 token based&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;All fields and modules are available through the API automatically&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Metadata API provides everything you need to know about your Sugar instance.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Topics
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/new-tutorial-intro-to-the-sugar-rest-api"&gt;Intro to the Sugar REST API&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/how-sugar-rest-api-versioning-works"&gt;How Sugar REST API versioning works&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/"&gt;RestAPI Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/sugarcrm-cookbook---the-school-of-rest---part-1"&gt;SugarCRM Cookbook - The School of REST - Part 1&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/"&gt;REST APIs Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Extending_Endpoints/"&gt;How to add your own custom endpoints to the REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/API_Exceptions/"&gt;API Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Best_Practices/"&gt;Best practices when integrating and migrating Sugar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="common"&gt;&lt;/a&gt;Common&amp;nbsp;APIs&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;It is important to understand our most commonly used APIs and their functions within Sugar. Your integration might need data within Sugar&amp;#39;s module structure that could potentially change over time, so you can use Metadata for it as well as CRUD onto Sugar.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Metadata
&lt;ul&gt;
&lt;li&gt;Endpoint with current system&amp;#39;s structure&lt;/li&gt;
&lt;li&gt;Modules, fields, relationships, layouts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Use carefully, its payload can be MBs in size, cache as much as possible&lt;/li&gt;
&lt;li&gt;GET /metadata (use filters as much as possible)&lt;/li&gt;
&lt;li&gt;It does not retrieve labels for dropdowns, use language API to do so&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/3-tips-for-using-the-sugar-metadata-api"&gt;3 Tips for using the Sugar Metadata API&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Language
&lt;ul&gt;
&lt;li&gt;Endpoint to retrieve labels&lt;/li&gt;
&lt;li&gt;Dropdown list values&lt;/li&gt;
&lt;li&gt;Any language-specific content&lt;/li&gt;
&lt;li&gt;GET /lang/&amp;lt;language_code&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;CRUD (Create, Read, Update, Delete) records&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_GET"&gt;Read&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/module_POST"&gt;Create&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;POST /&amp;lt;module&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_PUT"&gt;Update&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;PUT&amp;nbsp;&lt;span&gt;/&amp;lt;module&amp;gt;/:record&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_DELETE"&gt;Delete&lt;/a&gt;:&amp;nbsp;&lt;code&gt;DELETE&amp;nbsp;/&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulefilter_POST"&gt;Filter&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;POST /&amp;lt;module&amp;gt;/filter&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;You can use&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulefilter_GET"&gt;GET&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;as well&lt;/li&gt;
&lt;li&gt;POST solves the issue when a query is too long and hits HTTP limits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecordlinklink_name_GET"&gt;Retrieve records related to another module&lt;/a&gt;:&amp;nbsp;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record/link/:link_name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecordlinklink_nameremote_id_POST"&gt;Creates a relationship to a pre-existing record:&lt;/a&gt;&lt;code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;POST /&amp;lt;module&amp;gt;/:record/link/:link_name/:remote_id&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="performance"&gt;&lt;/a&gt;Performance and Best Practices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/h1&gt;
&lt;div class="row"&gt;
&lt;div class="col-xs-12 col-md-9"&gt;
&lt;p&gt;As you deep dive into Sugar APIs,&amp;nbsp;you will see how easy it is to integrate to pull and push data from and to Sugar and your systems, however, you must consider performance so your integration doesn&amp;#39;t become a bottleneck between those systems.&lt;/p&gt;
&lt;p&gt;You should consider the following guidelines when implementing your integrations:&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar&amp;#39;s sync_key to link to remote IDs
&lt;ul&gt;
&lt;li&gt;Sugar provides in every module a sync_key field&lt;/li&gt;
&lt;li&gt;sync_key is a unique identifier for that module that links back to your external system&amp;#39;s generated key&lt;/li&gt;
&lt;li&gt;For example, account ID from ERP is AC0001, set sync_key (pass as a parameter in the POST) and sugar will create a record in account with sync_key=AC0001&lt;/li&gt;
&lt;li&gt;Next patch/update, sugar will check &amp;quot;where sync_key=&amp;#39;AC0001&amp;#39;&amp;quot; and update it (it is indexed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Integrate Upsert APIs
&lt;ul&gt;
&lt;li&gt;Sugar&amp;#39;s &amp;quot;update or insert&amp;quot; API based on sync_key&lt;/li&gt;
&lt;li&gt;Simplifies a common operation - if record exists, update it, otherwise create it (GET followed by a&amp;nbsp;PUT or POST)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_PATCH"&gt;Upsert by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_GET"&gt;Get by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_DELETE"&gt;Delete by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulerecord_idsync_key_field_namesync_key_field_value_PATCH"&gt;Set a sync on existing record (without sync_key)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_POST"&gt;Create relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_DELETE"&gt;Delete relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Bulk API
&lt;ul&gt;
&lt;li&gt;An endpoint that encapsulates multiple API calls into one single HTTP request&lt;/li&gt;
&lt;li&gt;Requests are executed synchronously (one after the other)&lt;/li&gt;
&lt;li&gt;Reducing network latency between calls&lt;/li&gt;
&lt;li&gt;Combined with Upsert provides the best performance&lt;/li&gt;
&lt;li&gt;Careful not to add too many requests to it&lt;/li&gt;
&lt;li&gt;Start small (5 to 10 requests) and increase until you reach its max capacity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Polling and filtering time-based with Filter API
&lt;ul&gt;
&lt;li&gt;Integration gateway (or your external system) asks Sugar every X minutes&lt;/li&gt;
&lt;li&gt;Request Filter API using &lt;code&gt;max_num&lt;/code&gt; (max number of records), offset and fields&lt;/li&gt;
&lt;li&gt;The response will provide the data as well as &lt;code&gt;next_offset&lt;/code&gt; (offset can be seen as pagination)&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;next_offset&lt;/code&gt; is -1, no more records to go through&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Initial Data Load into Sugar&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Use Bulk + Upsert to achieve data loads&lt;/li&gt;
&lt;li&gt;Millions&amp;nbsp;of records may take a little while to process, plan ahead (over the weekend)&lt;/li&gt;
&lt;li&gt;Use multi-thread processes to load (for example 20 threads sending 20 bulk upsert requests)&lt;/li&gt;
&lt;li&gt;Careful with&amp;nbsp;&lt;a href="https://support.sugarcrm.com/Resources/Sugar_Cloud_Policy_Guide/#Rate_Limits"&gt;Sugar Cloud rate limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&amp;#39;s always a good idea to let Sugar Support know you&amp;#39;re data loading, they will be considerate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Understanding PHP limitations&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;PHP is single-threaded with limited resources to process your request&lt;/li&gt;
&lt;li&gt;If you send too much data using bulk, you may run out of memory for that request&lt;/li&gt;
&lt;li&gt;Push to the limits but give some room for PHP to finish the request gracefully&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Pagination for millions of records by using OFFSET will degrade performance
&lt;ul&gt;
&lt;li&gt;We rely on DB to find, sort and limit records&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/swlh/sql-pagination-you-are-probably-doing-it-wrong-d0f2719cc166"&gt;Nice article &lt;/a&gt;explaining how this works in details&lt;/li&gt;
&lt;li&gt;Instead of offsets, store the last processed ID and use it in the WHERE clause and sort by ID&lt;/li&gt;
&lt;li&gt;Example
&lt;ul&gt;
&lt;li&gt;Instead of: (/v11_25/Leads?max_num=1000&amp;amp;&lt;strong&gt;offset=4619000&lt;/strong&gt;&amp;amp;order_by=id)&lt;/li&gt;
&lt;li&gt;Do this&amp;nbsp;(/v11_25/Leads?&lt;strong&gt;filter=[{"id": {"$gt": &amp;rdquo;&amp;lt;last_id&amp;gt;"}}]&lt;/strong&gt;&amp;amp;max_num=1000&amp;amp;order_by=id)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If you need to add a date, make sure to add it as part of the filter and order&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p id="mcetoc_1f5uvkqns0"&gt;&lt;span style="font-size:150%;"&gt;You&amp;#39;re up and running, but don&amp;#39;t stop now - this is just the beginning of your journey. &lt;/span&gt;&lt;/p&gt;
&lt;p id="mcetoc_1g9jl704d0"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Now it&amp;#39;s time for&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/676/customization-for-product-devs"&gt;Customization for Product Devs&lt;/a&gt;.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Integrations for Product Devs</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs/revision/11</link><pubDate>Fri, 16 May 2025 14:49:39 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:e64c91c4-03e5-454f-bbd7-3beb25519ac3</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs#comments</comments><description>Revision 11 posted to Dev Tutorials by Rafael Fernandes on 5/16/2025 2:49:39 PM&lt;br /&gt;
&lt;table style="margin-left:auto;margin-right:auto;width:100%;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#approach"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#rest"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#common"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#performance"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="approach"&gt;&lt;/a&gt;Integration Approaches&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;The Sugar platform is extremely powerful, flexible, and allows for easy integration. This flexibility means that determining the&amp;nbsp;best approach for your use case scenario is the key to success.&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Push/Pull from Sugar via REST API&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="text-decoration:underline;"&gt;Recommended&lt;/span&gt; approach&lt;/li&gt;
&lt;li&gt;Developers have full control over integration&lt;/li&gt;
&lt;li&gt;Integration can be stopped and systems will continue to work&lt;/li&gt;
&lt;li&gt;Retry mechanism: Resume integrations at any time (identify deltas through &amp;quot;last_update_time&amp;quot; flags)&lt;/li&gt;
&lt;li&gt;The time delay from/to Sugar is minimal&lt;/li&gt;
&lt;li&gt;Sugar REST API offers almost everything you need,&amp;nbsp;and can be further extended via customization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push to Sugar, Sugar pushes to an external queue in realtime&lt;span&gt;&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar Events to trigger through Logic Hooks&lt;/li&gt;
&lt;li&gt;Requires&amp;nbsp;Logic Hooks (code customization) to be created and deployed&lt;/li&gt;
&lt;li&gt;Does not offer a &amp;quot;retry mechanism&amp;quot;, if a logic hook fails to deliver to a queue or contact an external system&lt;/li&gt;
&lt;li&gt;Synchronous in nature, requires a response from an external system&lt;/li&gt;
&lt;li&gt;Needs to handle dependencies manually (contact can only be created after account)&lt;/li&gt;
&lt;li&gt;Good to have a middleware/queue in front of Sugar to receive those event triggers to&amp;nbsp;reliably&amp;nbsp;manage peak loads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Realtime: Embed your app into Sugar&amp;nbsp;through &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/User_Interface/Dashlets/"&gt;Dashlets&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Simplest approach&lt;/li&gt;
&lt;li&gt;Often requires web user-based authentication&lt;/li&gt;
&lt;li&gt;All load/traffic goes directly to your system,&amp;nbsp;which makes your system the performance bottleneck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="rest"&gt;&lt;/a&gt;REST API Webservices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;Accessing your data when you want is good. Accessing your data however you want is better. &lt;/span&gt;&lt;span&gt;When you decide to build an integration with Sugar, you&amp;rsquo;ll need an easy way to access and interact with the data stored in Sugar. The REST (&lt;/span&gt;&lt;span&gt;representational state transfer)&lt;/span&gt;&lt;span&gt;&amp;nbsp;API (application programming interface) is perfect for this.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sugar REST API Overview
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Fully RESTfull (GET, POST, PUT, DELETE)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;OAuth2 token based&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;All fields and modules are available through the API automatically&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Metadata API provides everything you need to know about your Sugar instance.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Topics
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/new-tutorial-intro-to-the-sugar-rest-api"&gt;Intro to the Sugar REST API&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/how-sugar-rest-api-versioning-works"&gt;How Sugar REST API versioning works&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/"&gt;RestAPI Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/sugarcrm-cookbook---the-school-of-rest---part-1"&gt;SugarCRM Cookbook - The School of REST - Part 1&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/"&gt;REST APIs Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Extending_Endpoints/"&gt;How to add your own custom endpoints to the REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/API_Exceptions/"&gt;API Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Best_Practices/"&gt;Best practices when integrating and migrating Sugar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="common"&gt;&lt;/a&gt;Common&amp;nbsp;APIs&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;It is important to understand our most commonly used APIs and their functions within Sugar. Your integration might need data within Sugar&amp;#39;s module structure that could potentially change over time, so you can use Metadata for it as well as CRUD onto Sugar.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Metadata
&lt;ul&gt;
&lt;li&gt;Endpoint with current system&amp;#39;s structure&lt;/li&gt;
&lt;li&gt;Modules, fields, relationships, layouts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Use carefully, its payload can be MBs in size, cache as much as possible&lt;/li&gt;
&lt;li&gt;GET /metadata (use filters as much as possible)&lt;/li&gt;
&lt;li&gt;It does not retrieve labels for dropdowns, use language API to do so&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/3-tips-for-using-the-sugar-metadata-api"&gt;3 Tips for using the Sugar Metadata API&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Language
&lt;ul&gt;
&lt;li&gt;Endpoint to retrieve labels&lt;/li&gt;
&lt;li&gt;Dropdown list values&lt;/li&gt;
&lt;li&gt;Any language-specific content&lt;/li&gt;
&lt;li&gt;GET /lang/&amp;lt;language_code&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;CRUD (Create, Read, Update, Delete) records&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_GET"&gt;Read&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/module_POST"&gt;Create&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;POST /&amp;lt;module&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_PUT"&gt;Update&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;PUT&amp;nbsp;&lt;span&gt;/&amp;lt;module&amp;gt;/:record&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_DELETE"&gt;Delete&lt;/a&gt;:&amp;nbsp;&lt;code&gt;DELETE&amp;nbsp;/&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulefilter_POST"&gt;Filter&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;POST /&amp;lt;module&amp;gt;/filter&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;You can use&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulefilter_GET"&gt;GET&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;as well&lt;/li&gt;
&lt;li&gt;POST solves the issue when a query is too long and hits HTTP limits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecordlinklink_name_GET"&gt;Retrieve records related to another module&lt;/a&gt;:&amp;nbsp;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record/link/:link_name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecordlinklink_nameremote_id_POST"&gt;Creates a relationship to a pre-existing record:&lt;/a&gt;&lt;code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;POST /&amp;lt;module&amp;gt;/:record/link/:link_name/:remote_id&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="performance"&gt;&lt;/a&gt;Performance and Best Practices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/h1&gt;
&lt;div class="row"&gt;
&lt;div class="col-xs-12 col-md-9"&gt;
&lt;p&gt;As you deep dive into Sugar APIs,&amp;nbsp;you will see how easy it is to integrate to pull and push data from and to Sugar and your systems, however, you must consider performance so your integration doesn&amp;#39;t become a bottleneck between those systems.&lt;/p&gt;
&lt;p&gt;You should consider the following guidelines when implementing your integrations:&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar&amp;#39;s sync_key to link to remote IDs
&lt;ul&gt;
&lt;li&gt;Sugar provides in every module a sync_key field&lt;/li&gt;
&lt;li&gt;sync_key is a unique identifier for that module that links back to your external system&amp;#39;s generated key&lt;/li&gt;
&lt;li&gt;For example, account ID from ERP is AC0001, set sync_key (pass as a parameter in the POST) and sugar will create a record in account with sync_key=AC0001&lt;/li&gt;
&lt;li&gt;Next patch/update, sugar will check &amp;quot;where sync_key=&amp;#39;AC0001&amp;#39;&amp;quot; and update it (it is indexed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Integrate Upsert APIs
&lt;ul&gt;
&lt;li&gt;Sugar&amp;#39;s &amp;quot;update or insert&amp;quot; API based on sync_key&lt;/li&gt;
&lt;li&gt;Simplifies a common operation - if record exists, update it, otherwise create it (GET followed by a&amp;nbsp;PUT or POST)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_PATCH"&gt;Upsert by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_GET"&gt;Get by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_DELETE"&gt;Delete by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulerecord_idsync_key_field_namesync_key_field_value_PATCH"&gt;Set a sync on existing record (without sync_key)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_POST"&gt;Create relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_DELETE"&gt;Delete relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Bulk API
&lt;ul&gt;
&lt;li&gt;An endpoint that encapsulates multiple API calls into one single HTTP request&lt;/li&gt;
&lt;li&gt;Requests are executed synchronously (one after the other)&lt;/li&gt;
&lt;li&gt;Reducing network latency between calls&lt;/li&gt;
&lt;li&gt;Combined with Upsert provides the best performance&lt;/li&gt;
&lt;li&gt;Careful not to add too many requests to it&lt;/li&gt;
&lt;li&gt;Start small (5 to 10 requests) and increase until you reach its max capacity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Polling and filtering time-based with Filter API
&lt;ul&gt;
&lt;li&gt;Integration gateway (or your external system) asks Sugar every X minutes&lt;/li&gt;
&lt;li&gt;Request Filter API using &lt;code&gt;max_num&lt;/code&gt; (max number of records), offset and fields&lt;/li&gt;
&lt;li&gt;The response will provide the data as well as &lt;code&gt;next_offset&lt;/code&gt; (offset can be seen as pagination)&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;next_offset&lt;/code&gt; is -1, no more records to go through&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Initial Data Load into Sugar&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Use Bulk + Upsert to achieve data loads&lt;/li&gt;
&lt;li&gt;Millions&amp;nbsp;of records may take a little while to process, plan ahead (over the weekend)&lt;/li&gt;
&lt;li&gt;Use multi-thread processes to load (for example 20 threads sending 20 bulk upsert requests)&lt;/li&gt;
&lt;li&gt;Careful with&amp;nbsp;&lt;a href="https://support.sugarcrm.com/Resources/Sugar_Cloud_Policy_Guide/#Rate_Limits"&gt;Sugar Cloud rate limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&amp;#39;s always a good idea to let Sugar Support know you&amp;#39;re data loading, they will be considerate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Understanding PHP limitations&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;PHP is single-threaded with limited resources to process your request&lt;/li&gt;
&lt;li&gt;If you send too much data using bulk, you may run out of memory for that request&lt;/li&gt;
&lt;li&gt;Push to the limits but give some room for PHP to finish the request gracefully&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Pagination for millions of records by using OFFSET will degrade performance
&lt;ul&gt;
&lt;li&gt;We rely on DB to find, sort and limit records&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/swlh/sql-pagination-you-are-probably-doing-it-wrong-d0f2719cc166"&gt;Nice article &lt;/a&gt;explaining how this works in details&lt;/li&gt;
&lt;li&gt;Instead of offsets, store the last processed ID and use it in the WHERE clause and sort by ID&lt;/li&gt;
&lt;li&gt;Example
&lt;ul&gt;
&lt;li&gt;Instead of: (/v11_25/Leads?max_num=1000&amp;amp;&lt;strong&gt;offset=4619000&lt;/strong&gt;&amp;amp;order_by=id)&lt;/li&gt;
&lt;li&gt;Do this&amp;nbsp;(/v11_25/Leads?&lt;strong&gt;filter=[{"id": {"$gt": &amp;rdquo;&amp;lt;last_id&amp;gt;"}}]&lt;/strong&gt;&amp;amp;max_num=1000&amp;amp;order_by=id)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If you need to add a date, make sure to add it as part of the filter and order&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p id="mcetoc_1f5uvkqns0"&gt;&lt;span style="font-size:150%;"&gt;You&amp;#39;re up and running, but don&amp;#39;t stop now - this is just the beginning of your journey. &lt;/span&gt;&lt;/p&gt;
&lt;p id="mcetoc_1g9jl704d0"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Now it&amp;#39;s time for&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/676/customization-for-product-devs"&gt;Customization for Product Devs&lt;/a&gt;.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Integrations for Product Devs</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs/revision/10</link><pubDate>Fri, 07 Feb 2025 17:37:12 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:e64c91c4-03e5-454f-bbd7-3beb25519ac3</guid><dc:creator>Alex Nassi</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs#comments</comments><description>Revision 10 posted to Dev Tutorials by Alex Nassi on 2/7/2025 5:37:12 PM&lt;br /&gt;
&lt;table style="margin-left:auto;margin-right:auto;width:100%;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#approach"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#rest"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#common"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#performance"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="approach"&gt;&lt;/a&gt;Integration Approaches&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;The Sugar platform is extremely powerful, flexible, and allows for easy integration. This flexibility means that determining the&amp;nbsp;best approach for your use case scenario is the key to success.&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Push/Pull from Sugar via REST API&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="text-decoration:underline;"&gt;Recommended&lt;/span&gt; approach&lt;/li&gt;
&lt;li&gt;Developers have full control over integration&lt;/li&gt;
&lt;li&gt;Integration can be stopped and systems will continue to work&lt;/li&gt;
&lt;li&gt;Retry mechanism: Resume integrations at any time (identify deltas through &amp;quot;last_update_time&amp;quot; flags)&lt;/li&gt;
&lt;li&gt;The time delay from/to Sugar is minimal&lt;/li&gt;
&lt;li&gt;Sugar REST API offers almost everything you need,&amp;nbsp;and can be further extended via customization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push to Sugar, Sugar pushes to an external queue in realtime&lt;span&gt;&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar Events to trigger through Logic Hooks&lt;/li&gt;
&lt;li&gt;Requires&amp;nbsp;Logic Hooks (code customization) to be created and deployed&lt;/li&gt;
&lt;li&gt;Does not offer a &amp;quot;retry mechanism&amp;quot;, if a logic hook fails to deliver to a queue or contact an external system&lt;/li&gt;
&lt;li&gt;Synchronous in nature, requires a response from an external system&lt;/li&gt;
&lt;li&gt;Needs to handle dependencies manually (contact can only be created after account)&lt;/li&gt;
&lt;li&gt;Good to have a middleware/queue in front of Sugar to receive those event triggers to&amp;nbsp;reliably&amp;nbsp;manage peak loads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Realtime: Embed your app into Sugar&amp;nbsp;through &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/User_Interface/Dashlets/"&gt;Dashlets&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Simplest approach&lt;/li&gt;
&lt;li&gt;Often requires web user-based authentication&lt;/li&gt;
&lt;li&gt;All load/traffic goes directly to your system,&amp;nbsp;which makes your system the performance bottleneck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="rest"&gt;&lt;/a&gt;REST API Webservices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;Accessing your data when you want is good. Accessing your data however you want is better. &lt;/span&gt;&lt;span&gt;When you decide to build an integration with Sugar, you&amp;rsquo;ll need an easy way to access and interact with the data stored in Sugar. The REST (&lt;/span&gt;&lt;span&gt;representational state transfer)&lt;/span&gt;&lt;span&gt;&amp;nbsp;API (application programming interface) is perfect for this.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sugar REST API Overview
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Fully RESTfull (GET, POST, PUT, DELETE)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;OAuth2 token based&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;All fields and modules are available through the API automatically&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Metadata API provides everything you need to know about your Sugar instance.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Topics
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/new-tutorial-intro-to-the-sugar-rest-api"&gt;Intro to the Sugar REST API&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/how-sugar-rest-api-versioning-works"&gt;How Sugar REST API versioning works&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/"&gt;RestAPI Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/sugarcrm-cookbook---the-school-of-rest---part-1"&gt;SugarCRM Cookbook - The School of REST - Part 1&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/"&gt;REST APIs Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Extending_Endpoints/"&gt;How to add your own custom endpoints to the REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/API_Exceptions/"&gt;API Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Best_Practices/"&gt;Best practices when integrating and migrating Sugar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="common"&gt;&lt;/a&gt;Common&amp;nbsp;APIs&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;It is important to understand our most commonly used APIs and their functions within Sugar. Your integration might need data within Sugar&amp;#39;s module structure that could potentially change over time, so you can use Metadata for it as well as CRUD onto Sugar.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Metadata
&lt;ul&gt;
&lt;li&gt;Endpoint with current system&amp;#39;s structure&lt;/li&gt;
&lt;li&gt;Modules, fields, relationships, layouts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Use carefully, its payload can be MBs in size, cache as much as possible&lt;/li&gt;
&lt;li&gt;GET /metadata (use filters as much as possible)&lt;/li&gt;
&lt;li&gt;It does not retrieve labels for dropdowns, use language API to do so&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/b/dev-blog/posts/3-tips-for-using-the-sugar-metadata-api"&gt;3 Tips for using the Sugar Metadata API&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Language
&lt;ul&gt;
&lt;li&gt;Endpoint to retrieve labels&lt;/li&gt;
&lt;li&gt;Dropdown list values&lt;/li&gt;
&lt;li&gt;Any language-specific content&lt;/li&gt;
&lt;li&gt;GET /lang/&amp;lt;language_code&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;CRUD (Create, Read, Update, Delete) records&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_GET"&gt;Read&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/module_POST"&gt;Create&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;POST /&amp;lt;module&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_PUT"&gt;Update&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;PUT&amp;nbsp;&lt;span&gt;/&amp;lt;module&amp;gt;/:record&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_DELETE"&gt;Delete&lt;/a&gt;:&amp;nbsp;&lt;code&gt;DELETE&amp;nbsp;/&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulefilter_POST"&gt;Filter&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;POST /&amp;lt;module&amp;gt;/filter&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;You can use&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulefilter_GET"&gt;GET&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;as well&lt;/li&gt;
&lt;li&gt;POST solves the issue when a query is too long and hits HTTP limits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecordlinklink_name_GET"&gt;Retrieve records related to another module&lt;/a&gt;:&amp;nbsp;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record/link/:link_name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecordlinklink_nameremote_id_POST"&gt;Creates a relationship to a pre-existing record:&lt;/a&gt;&lt;code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;POST /&amp;lt;module&amp;gt;/:record/link/:link_name/:remote_id&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="performance"&gt;&lt;/a&gt;Performance and Best Practices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/h1&gt;
&lt;div class="row"&gt;
&lt;div class="col-xs-12 col-md-9"&gt;
&lt;p&gt;As you deep dive into Sugar APIs,&amp;nbsp;you will see how easy it is to integrate to pull and push data from and to Sugar and your systems, however, you must consider performance so your integration doesn&amp;#39;t become a bottleneck between those systems.&lt;/p&gt;
&lt;p&gt;You should consider the following guidelines when implementing your integrations:&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar&amp;#39;s sync_key to link to remote IDs
&lt;ul&gt;
&lt;li&gt;Sugar provides in every module a sync_key field&lt;/li&gt;
&lt;li&gt;sync_key is a unique identifier for that module that links back to your external system&amp;#39;s generated key&lt;/li&gt;
&lt;li&gt;For example, account ID from ERP is AC0001, set sync_key (pass as a parameter in the POST) and sugar will create a record in account with sync_key=AC0001&lt;/li&gt;
&lt;li&gt;Next patch/update, sugar will check &amp;quot;where sync_key=&amp;#39;AC0001&amp;#39;&amp;quot; and update it (it is indexed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Integrate Upsert APIs
&lt;ul&gt;
&lt;li&gt;Sugar&amp;#39;s &amp;quot;update or insert&amp;quot; API based on sync_key&lt;/li&gt;
&lt;li&gt;Simplifies a common operation - if record exists, update it, otherwise create it (GET followed by a&amp;nbsp;PUT or POST)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_PATCH"&gt;Upsert by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_GET"&gt;Get by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_DELETE"&gt;Delete by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulerecord_idsync_key_field_namesync_key_field_value_PATCH"&gt;Set a sync on existing record (without sync_key)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_POST"&gt;Create relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_DELETE"&gt;Delete relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Bulk API
&lt;ul&gt;
&lt;li&gt;An endpoint that encapsulates multiple API calls into one single HTTP request&lt;/li&gt;
&lt;li&gt;Requests are executed synchronously (one after the other)&lt;/li&gt;
&lt;li&gt;Reducing network latency between calls&lt;/li&gt;
&lt;li&gt;Combined with Upsert provides the best performance&lt;/li&gt;
&lt;li&gt;Careful not to add too many requests to it&lt;/li&gt;
&lt;li&gt;Start small (5 to 10 requests) and increase until you reach its max capacity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Polling and filtering time-based with Filter API
&lt;ul&gt;
&lt;li&gt;Integration gateway (or your external system) asks Sugar every X minutes&lt;/li&gt;
&lt;li&gt;Request Filter API using &lt;code&gt;max_num&lt;/code&gt; (max number of records), offset and fields&lt;/li&gt;
&lt;li&gt;The response will provide the data as well as &lt;code&gt;next_offset&lt;/code&gt; (offset can be seen as pagination)&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;next_offset&lt;/code&gt; is -1, no more records to go through&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Initial Data Load into Sugar&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Use Bulk + Upsert to achieve data loads&lt;/li&gt;
&lt;li&gt;Millions&amp;nbsp;of records may take a little while to process, plan ahead (over the weekend)&lt;/li&gt;
&lt;li&gt;Use multi-thread processes to load (for example 20 threads sending 20 bulk upsert requests)&lt;/li&gt;
&lt;li&gt;Careful with&amp;nbsp;&lt;a href="https://support.sugarcrm.com/Resources/Sugar_Cloud_Policy_Guide/#Rate_Limits"&gt;Sugar Cloud rate limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&amp;#39;s always a good idea to let Sugar Support know you&amp;#39;re data loading, they will be considerate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Understanding PHP limitations&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;PHP is single-threaded with limited resources to process your request&lt;/li&gt;
&lt;li&gt;If you send too much data using bulk, you may run out of memory for that request&lt;/li&gt;
&lt;li&gt;Push to the limits but give some room for PHP to finish the request gracefully&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Pagination for millions of records by using OFFSET will degrade performance
&lt;ul&gt;
&lt;li&gt;We rely on DB to find, sort and limit records&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/swlh/sql-pagination-you-are-probably-doing-it-wrong-d0f2719cc166"&gt;Nice article &lt;/a&gt;explaining how this works in details&lt;/li&gt;
&lt;li&gt;Instead of offsets, store the last processed ID and use it in the WHERE clause and sort by ID&lt;/li&gt;
&lt;li&gt;Example
&lt;ul&gt;
&lt;li&gt;Instead of: (/v11_25/Leads?max_num=1000&amp;amp;&lt;strong&gt;offset=4619000&lt;/strong&gt;&amp;amp;order_by=id)&lt;/li&gt;
&lt;li&gt;Do this&amp;nbsp;(/v11_25/Leads?&lt;strong&gt;filter=[{"id":&amp;rdquo;&amp;lt;last_id&amp;gt;"}]&lt;/strong&gt;&amp;amp;max_num=1000&amp;amp;order_by=id)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If you need to add a date, make sure to add it as part of the filter and order&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p id="mcetoc_1f5uvkqns0"&gt;&lt;span style="font-size:150%;"&gt;You&amp;#39;re up and running, but don&amp;#39;t stop now - this is just the beginning of your journey. &lt;/span&gt;&lt;/p&gt;
&lt;p id="mcetoc_1g9jl704d0"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Now it&amp;#39;s time for&amp;nbsp;&lt;a href="https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/676/customization-for-product-devs"&gt;Customization for Product Devs&lt;/a&gt;.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Integrations for Product Devs</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs/revision/9</link><pubDate>Fri, 24 Jan 2025 16:49:06 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:e64c91c4-03e5-454f-bbd7-3beb25519ac3</guid><dc:creator>Alex Nassi</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs#comments</comments><description>Revision 9 posted to Dev Tutorials by Alex Nassi on 1/24/2025 4:49:06 PM&lt;br /&gt;
&lt;table style="margin-left:auto;margin-right:auto;width:100%;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#approach"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#rest"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#common"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#performance"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="approach"&gt;&lt;/a&gt;Integration Approaches&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;The Sugar platform is extremely powerful, flexible, and allows for easy integration. This flexibility means that determining the&amp;nbsp;best approach for your use case scenario is the key to success.&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Push/Pull from Sugar via REST API&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="text-decoration:underline;"&gt;Recommended&lt;/span&gt; approach&lt;/li&gt;
&lt;li&gt;Developers have full control over integration&lt;/li&gt;
&lt;li&gt;Integration can be stopped and systems will continue to work&lt;/li&gt;
&lt;li&gt;Retry mechanism: Resume integrations at any time (identify deltas through &amp;quot;last_update_time&amp;quot; flags)&lt;/li&gt;
&lt;li&gt;The time delay from/to Sugar is minimal&lt;/li&gt;
&lt;li&gt;Sugar REST API offers almost everything you need,&amp;nbsp;and can be further extended via customization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push to Sugar, Sugar pushes to an external queue in realtime&lt;span&gt;&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar Events to trigger through Logic Hooks&lt;/li&gt;
&lt;li&gt;Requires&amp;nbsp;Logic Hooks (code customization) to be created and deployed&lt;/li&gt;
&lt;li&gt;Does not offer a &amp;quot;retry mechanism&amp;quot;, if a logic hook fails to deliver to a queue or contact an external system&lt;/li&gt;
&lt;li&gt;Synchronous in nature, requires a response from an external system&lt;/li&gt;
&lt;li&gt;Needs to handle dependencies manually (contact can only be created after account)&lt;/li&gt;
&lt;li&gt;Good to have a middleware/queue in front of Sugar to receive those event triggers to&amp;nbsp;reliably&amp;nbsp;manage peak loads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Realtime: Embed your app into Sugar&amp;nbsp;through &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/User_Interface/Dashlets/"&gt;Dashlets&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Simplest approach&lt;/li&gt;
&lt;li&gt;Often requires web user-based authentication&lt;/li&gt;
&lt;li&gt;All load/traffic goes directly to your system,&amp;nbsp;which makes your system the performance bottleneck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="rest"&gt;&lt;/a&gt;REST API Webservices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;Accessing your data when you want is good. Accessing your data however you want is better. &lt;/span&gt;&lt;span&gt;When you decide to build an integration with Sugar, you&amp;rsquo;ll need an easy way to access and interact with the data stored in Sugar. The REST (&lt;/span&gt;&lt;span&gt;representational state transfer)&lt;/span&gt;&lt;span&gt;&amp;nbsp;API (application programming interface) is perfect for this.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sugar REST API Overview
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Fully RESTfull (GET, POST, PUT, DELETE)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;OAuth2 token based&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;All fields and modules are available through the API automatically&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Metadata API provides everything you need to know about your Sugar instance.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Topics
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/new-tutorial-intro-to-the-sugar-rest-api"&gt;Intro to the Sugar REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/how-sugar-rest-api-versioning-works"&gt;How Sugar REST API versioning works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/"&gt;RestAPI Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/sugarcrm-cookbook---the-school-of-rest---part-1"&gt;School of REST blog series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/"&gt;REST APIs Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Extending_Endpoints/"&gt;How to add your own custom endpoints to the REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/API_Exceptions/"&gt;API Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Best_Practices/"&gt;Best practices when integrating and migrating Sugar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="common"&gt;&lt;/a&gt;Common&amp;nbsp;APIs&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;It is important to understand our most commonly used APIs and their functions within Sugar. Your integration might need data within Sugar&amp;#39;s module structure that could potentially change over time, so you can use Metadata for it as well as CRUD onto Sugar.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Metadata
&lt;ul&gt;
&lt;li&gt;Endpoint with current system&amp;#39;s structure&lt;/li&gt;
&lt;li&gt;Modules, fields, relationships, layouts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Use carefully, its payload can be MBs in size, cache as much as possible&lt;/li&gt;
&lt;li&gt;GET /metadata (use filters as much as possible)&lt;/li&gt;
&lt;li&gt;It does not retrieve labels for dropdowns, use language API to do so&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/3-tips-for-using-the-sugar-metadata-api"&gt;3 Tips for using the Sugar Metadata API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Language
&lt;ul&gt;
&lt;li&gt;Endpoint to retrieve labels&lt;/li&gt;
&lt;li&gt;Dropdown list values&lt;/li&gt;
&lt;li&gt;Any language-specific content&lt;/li&gt;
&lt;li&gt;GET /lang/&amp;lt;language_code&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;CRUD (Create, Read, Update, Delete) records&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_GET"&gt;Read&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/module_POST"&gt;Create&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;POST /&amp;lt;module&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_PUT"&gt;Update&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;PUT&amp;nbsp;&lt;span&gt;/&amp;lt;module&amp;gt;/:record&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_DELETE"&gt;Delete&lt;/a&gt;:&amp;nbsp;&lt;code&gt;DELETE&amp;nbsp;/&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulefilter_POST"&gt;Filter&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;POST /&amp;lt;module&amp;gt;/filter&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;You can use&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulefilter_GET"&gt;GET&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;as well&lt;/li&gt;
&lt;li&gt;POST solves the issue when a query is too long and hits HTTP limits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecordlinklink_name_GET"&gt;Retrieve records related to another module&lt;/a&gt;:&amp;nbsp;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record/link/:link_name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecordlinklink_nameremote_id_POST"&gt;Creates a relationship to a pre-existing record:&lt;/a&gt;&lt;code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;POST /&amp;lt;module&amp;gt;/:record/link/:link_name/:remote_id&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="performance"&gt;&lt;/a&gt;Performance and Best Practices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/h1&gt;
&lt;div class="row"&gt;
&lt;div class="col-xs-12 col-md-9"&gt;
&lt;p&gt;As you deep dive into Sugar APIs,&amp;nbsp;you will see how easy it is to integrate to pull and push data from and to Sugar and your systems, however, you must consider performance so your integration doesn&amp;#39;t become a bottleneck between those systems.&lt;/p&gt;
&lt;p&gt;You should consider the following guidelines when implementing your integrations:&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar&amp;#39;s sync_key to link to remote IDs
&lt;ul&gt;
&lt;li&gt;Sugar provides in every module a sync_key field&lt;/li&gt;
&lt;li&gt;sync_key is a unique identifier for that module that links back to your external system&amp;#39;s generated key&lt;/li&gt;
&lt;li&gt;For example, account ID from ERP is AC0001, set sync_key (pass as a parameter in the POST) and sugar will create a record in account with sync_key=AC0001&lt;/li&gt;
&lt;li&gt;Next patch/update, sugar will check &amp;quot;where sync_key=&amp;#39;AC0001&amp;#39;&amp;quot; and update it (it is indexed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Integrate Upsert APIs
&lt;ul&gt;
&lt;li&gt;Sugar&amp;#39;s &amp;quot;update or insert&amp;quot; API based on sync_key&lt;/li&gt;
&lt;li&gt;Simplifies a common operation - if record exists, update it, otherwise create it (GET followed by a&amp;nbsp;PUT or POST)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_PATCH"&gt;Upsert by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_GET"&gt;Get by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_DELETE"&gt;Delete by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulerecord_idsync_key_field_namesync_key_field_value_PATCH"&gt;Set a sync on existing record (without sync_key)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_POST"&gt;Create relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_DELETE"&gt;Delete relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Bulk API
&lt;ul&gt;
&lt;li&gt;An endpoint that encapsulates multiple API calls into one single HTTP request&lt;/li&gt;
&lt;li&gt;Requests are executed synchronously (one after the other)&lt;/li&gt;
&lt;li&gt;Reducing network latency between calls&lt;/li&gt;
&lt;li&gt;Combined with Upsert provides the best performance&lt;/li&gt;
&lt;li&gt;Careful not to add too many requests to it&lt;/li&gt;
&lt;li&gt;Start small (5 to 10 requests) and increase until you reach its max capacity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Polling and filtering time-based with Filter API
&lt;ul&gt;
&lt;li&gt;Integration gateway (or your external system) asks Sugar every X minutes&lt;/li&gt;
&lt;li&gt;Request Filter API using &lt;code&gt;max_num&lt;/code&gt; (max number of records), offset and fields&lt;/li&gt;
&lt;li&gt;The response will provide the data as well as &lt;code&gt;next_offset&lt;/code&gt; (offset can be seen as pagination)&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;next_offset&lt;/code&gt; is -1, no more records to go through&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Initial Data Load into Sugar&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Use Bulk + Upsert to achieve data loads&lt;/li&gt;
&lt;li&gt;Millions&amp;nbsp;of records may take a little while to process, plan ahead (over the weekend)&lt;/li&gt;
&lt;li&gt;Use multi-thread processes to load (for example 20 threads sending 20 bulk upsert requests)&lt;/li&gt;
&lt;li&gt;Careful with&amp;nbsp;&lt;a href="https://support.sugarcrm.com/Resources/Sugar_Cloud_Policy_Guide/#Rate_Limits"&gt;Sugar Cloud rate limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&amp;#39;s always a good idea to let Sugar Support know you&amp;#39;re data loading, they will be considerate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Understanding PHP limitations&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;PHP is single-threaded with limited resources to process your request&lt;/li&gt;
&lt;li&gt;If you send too much data using bulk, you may run out of memory for that request&lt;/li&gt;
&lt;li&gt;Push to the limits but give some room for PHP to finish the request gracefully&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Pagination for millions of records by using OFFSET will degrade performance
&lt;ul&gt;
&lt;li&gt;We rely on DB to find, sort and limit records&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/swlh/sql-pagination-you-are-probably-doing-it-wrong-d0f2719cc166"&gt;Nice article &lt;/a&gt;explaining how this works in details&lt;/li&gt;
&lt;li&gt;Instead of offsets, store the last processed ID and use it in the WHERE clause and sort by ID&lt;/li&gt;
&lt;li&gt;Example
&lt;ul&gt;
&lt;li&gt;Instead of: (/v11_25/Leads?max_num=1000&amp;amp;&lt;strong&gt;offset=4619000&lt;/strong&gt;&amp;amp;order_by=id)&lt;/li&gt;
&lt;li&gt;Do this&amp;nbsp;(/v11_25/Leads?&lt;strong&gt;filter=[{"id":&amp;rdquo;&amp;lt;last_id&amp;gt;"}]&lt;/strong&gt;&amp;amp;max_num=1000&amp;amp;order_by=id)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If you need to add a date, make sure to add it as part of the filter and order&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p id="mcetoc_1f5uvkqns0"&gt;&lt;span style="font-size:150%;"&gt;You&amp;#39;re up and running, but don&amp;#39;t stop now - this is just the beginning of your journey. &lt;/span&gt;&lt;/p&gt;
&lt;p id="mcetoc_1g9jl704d0"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Now it&amp;#39;s time for &lt;a href="https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/676/customization-for-product-devs"&gt;Customization for Product Devs&lt;/a&gt;.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Integrations for Product Devs</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs/revision/8</link><pubDate>Thu, 22 Aug 2024 15:00:04 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:e64c91c4-03e5-454f-bbd7-3beb25519ac3</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs#comments</comments><description>Revision 8 posted to Dev Tutorials by Rafael Fernandes on 8/22/2024 3:00:04 PM&lt;br /&gt;
&lt;table style="margin-left:auto;margin-right:auto;width:100%;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#approach"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#rest"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#common"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#performance"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="approach"&gt;&lt;/a&gt;Integration Approaches&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;The Sugar platform is extremely powerful, flexible, and allows for easy integration. This flexibility means that determining the&amp;nbsp;best approach for your use case scenario is the key to success.&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Push/Pull from Sugar via REST API&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="text-decoration:underline;"&gt;Recommended&lt;/span&gt; approach&lt;/li&gt;
&lt;li&gt;Developers have full control over integration&lt;/li&gt;
&lt;li&gt;Integration can be stopped and systems will continue to work&lt;/li&gt;
&lt;li&gt;Retry mechanism: Resume integrations at any time (identify deltas through &amp;quot;last_update_time&amp;quot; flags)&lt;/li&gt;
&lt;li&gt;The time delay from/to Sugar is minimal&lt;/li&gt;
&lt;li&gt;Sugar REST API offers almost everything you need,&amp;nbsp;and can be further extended via customization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push to Sugar, Sugar pushes to an external queue in realtime&lt;span&gt;&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar Events to trigger through Logic Hooks&lt;/li&gt;
&lt;li&gt;Requires&amp;nbsp;Logic Hooks (code customization) to be created and deployed&lt;/li&gt;
&lt;li&gt;Does not offer a &amp;quot;retry mechanism&amp;quot;, if a logic hook fails to deliver to a queue or contact an external system&lt;/li&gt;
&lt;li&gt;Synchronous in nature, requires a response from an external system&lt;/li&gt;
&lt;li&gt;Needs to handle dependencies manually (contact can only be created after account)&lt;/li&gt;
&lt;li&gt;Good to have a middleware/queue in front of Sugar to receive those event triggers to&amp;nbsp;reliably&amp;nbsp;manage peak loads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Realtime: Embed your app into Sugar&amp;nbsp;through &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/User_Interface/Dashlets/"&gt;Dashlets&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Simplest approach&lt;/li&gt;
&lt;li&gt;Often requires web user-based authentication&lt;/li&gt;
&lt;li&gt;All load/traffic goes directly to your system,&amp;nbsp;which makes your system the performance bottleneck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="rest"&gt;&lt;/a&gt;REST API Webservices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;Accessing your data when you want is good. Accessing your data however you want is better. &lt;/span&gt;&lt;span&gt;When you decide to build an integration with Sugar, you&amp;rsquo;ll need an easy way to access and interact with the data stored in Sugar. The REST (&lt;/span&gt;&lt;span&gt;representational state transfer)&lt;/span&gt;&lt;span&gt;&amp;nbsp;API (application programming interface) is perfect for this.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sugar REST API Overview
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Fully RESTfull (GET, POST, PUT, DELETE)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;OAuth2 token based&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;All fields and modules are available through the API automatically&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Metadata API provides everything you need to know about your Sugar instance.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Topics
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/new-tutorial-intro-to-the-sugar-rest-api"&gt;Intro to the Sugar REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/how-sugar-rest-api-versioning-works"&gt;How Sugar REST API versioning works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/"&gt;RestAPI Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/sugarcrm-cookbook---the-school-of-rest---part-1"&gt;School of REST blog series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/"&gt;REST APIs Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Extending_Endpoints/"&gt;How to add your own custom endpoints to the REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/API_Exceptions/"&gt;API Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Best_Practices/"&gt;Best practices when integrating and migrating Sugar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="common"&gt;&lt;/a&gt;Common&amp;nbsp;APIs&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;It is important to understand our most commonly used APIs and their functions within Sugar. Your integration might need data within Sugar&amp;#39;s module structure that could potentially change over time, so you can use Metadata for it as well as CRUD onto Sugar.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Metadata
&lt;ul&gt;
&lt;li&gt;Endpoint with current system&amp;#39;s structure&lt;/li&gt;
&lt;li&gt;Modules, fields, relationships, layouts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Use carefully, its payload can be MBs in size, cache as much as possible&lt;/li&gt;
&lt;li&gt;GET /metadata (use filters as much as possible)&lt;/li&gt;
&lt;li&gt;It does not retrieve labels for dropdowns, use language API to do so&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/3-tips-for-using-the-sugar-metadata-api"&gt;3 Tips for using the Sugar Metadata API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Language
&lt;ul&gt;
&lt;li&gt;Endpoint to retrieve labels&lt;/li&gt;
&lt;li&gt;Dropdown list values&lt;/li&gt;
&lt;li&gt;Any language-specific content&lt;/li&gt;
&lt;li&gt;GET /lang/&amp;lt;language_code&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;CRUD (Create, Read, Update, Delete) records&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_GET"&gt;Read&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/module_POST"&gt;Create&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;POST /&amp;lt;module&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_PUT"&gt;Update&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;PUT&amp;nbsp;&lt;span&gt;/&amp;lt;module&amp;gt;/:record&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecord_DELETE"&gt;Delete&lt;/a&gt;:&amp;nbsp;&lt;code&gt;DELETE&amp;nbsp;/&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulefilter_POST"&gt;Filter&lt;/a&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;POST /&amp;lt;module&amp;gt;/filter&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;You can use&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulefilter_GET"&gt;GET&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;as well&lt;/li&gt;
&lt;li&gt;POST solves the issue when a query is too long and hits HTTP limits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecordlinklink_name_GET"&gt;Retrieve records related to another module&lt;/a&gt;:&amp;nbsp;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record/link/:link_name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/rest_api/Endpoints/modulerecordlinklink_nameremote_id_POST"&gt;Creates a relationship to a pre-existing record:&lt;/a&gt;&lt;code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;POST /&amp;lt;module&amp;gt;/:record/link/:link_name/:remote_id&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="performance"&gt;&lt;/a&gt;Performance and Best Practices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/h1&gt;
&lt;div class="row"&gt;
&lt;div class="col-xs-12 col-md-9"&gt;
&lt;p&gt;As you deep dive into Sugar APIs,&amp;nbsp;you will see how easy it is to integrate to pull and push data from and to Sugar and your systems, however, you must consider performance so your integration doesn&amp;#39;t become a bottleneck between those systems.&lt;/p&gt;
&lt;p&gt;You should consider the following guidelines when implementing your integrations:&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar&amp;#39;s sync_key to link to remote IDs
&lt;ul&gt;
&lt;li&gt;Sugar provides in every module a sync_key field&lt;/li&gt;
&lt;li&gt;sync_key is a unique identifier for that module that links back to your external system&amp;#39;s generated key&lt;/li&gt;
&lt;li&gt;For example, account ID from ERP is AC0001, set sync_key (pass as a parameter in the POST) and sugar will create a record in account with sync_key=AC0001&lt;/li&gt;
&lt;li&gt;Next patch/update, sugar will check &amp;quot;where sync_key=&amp;#39;AC0001&amp;#39;&amp;quot; and update it (it is indexed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Integrate Upsert APIs
&lt;ul&gt;
&lt;li&gt;Sugar&amp;#39;s &amp;quot;update or insert&amp;quot; API based on sync_key&lt;/li&gt;
&lt;li&gt;Simplifies a common operation - if record exists, update it, otherwise create it (GET followed by a&amp;nbsp;PUT or POST)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_PATCH"&gt;Upsert by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_GET"&gt;Get by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_DELETE"&gt;Delete by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulerecord_idsync_key_field_namesync_key_field_value_PATCH"&gt;Set a sync on existing record (without sync_key)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_POST"&gt;Create relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_DELETE"&gt;Delete relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Bulk API
&lt;ul&gt;
&lt;li&gt;An endpoint that encapsulates multiple API calls into one single HTTP request&lt;/li&gt;
&lt;li&gt;Requests are executed synchronously (one after the other)&lt;/li&gt;
&lt;li&gt;Reducing network latency between calls&lt;/li&gt;
&lt;li&gt;Combined with Upsert provides the best performance&lt;/li&gt;
&lt;li&gt;Careful not to add too many requests to it&lt;/li&gt;
&lt;li&gt;Start small (5 to 10 requests) and increase until you reach its max capacity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Polling and filtering time-based with Filter API
&lt;ul&gt;
&lt;li&gt;Integration gateway (or your external system) asks Sugar every X minutes&lt;/li&gt;
&lt;li&gt;Request Filter API using &lt;code&gt;max_num&lt;/code&gt; (max number of records), offset and fields&lt;/li&gt;
&lt;li&gt;The response will provide the data as well as &lt;code&gt;next_offset&lt;/code&gt; (offset can be seen as pagination)&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;next_offset&lt;/code&gt; is -1, no more records to go through&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Initial Data Load into Sugar&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Use Bulk + Upsert to achieve data loads&lt;/li&gt;
&lt;li&gt;Millions&amp;nbsp;of records may take a little while to process, plan ahead (over the weekend)&lt;/li&gt;
&lt;li&gt;Use multi-thread processes to load (for example 20 threads sending 20 bulk upsert requests)&lt;/li&gt;
&lt;li&gt;Careful with&amp;nbsp;&lt;a href="https://support.sugarcrm.com/Resources/Sugar_Cloud_Policy_Guide/#Rate_Limits"&gt;Sugar Cloud rate limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&amp;#39;s always a good idea to let Sugar Support know you&amp;#39;re data loading, they will be considerate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Understanding PHP limitations&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;PHP is single-threaded with limited resources to process your request&lt;/li&gt;
&lt;li&gt;If you send too much data using bulk, you may run out of memory for that request&lt;/li&gt;
&lt;li&gt;Push to the limits but give some room for PHP to finish the request gracefully&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Pagination for millions of records by using OFFSET will degrade performance
&lt;ul&gt;
&lt;li&gt;We rely on DB to find, sort and limit records&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/swlh/sql-pagination-you-are-probably-doing-it-wrong-d0f2719cc166"&gt;Nice article &lt;/a&gt;explaining how this works in details&lt;/li&gt;
&lt;li&gt;Instead of offsets, store the last processed ID and use it in the WHERE clause and sort by ID&lt;/li&gt;
&lt;li&gt;Example
&lt;ul&gt;
&lt;li&gt;Instead of: (/v11_25/Leads?max_num=1000&amp;amp;&lt;strong&gt;offset=4619000&lt;/strong&gt;&amp;amp;order_by=id)&lt;/li&gt;
&lt;li&gt;Do this&amp;nbsp;(/v11_25/Leads?&lt;strong&gt;filter=[{"id":&amp;rdquo;&amp;lt;last_id&amp;gt;"}]&lt;/strong&gt;&amp;amp;max_num=1000&amp;amp;order_by=id)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If you need to add a date, make sure to add it as part of the filter and order&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p id="mcetoc_1f5uvkqns0"&gt;&lt;span style="font-size:150%;"&gt;You&amp;#39;re up and running, but don&amp;#39;t stop now - this is just the beginning of your journey. &lt;/span&gt;&lt;/p&gt;
&lt;p id="mcetoc_1g9jl704d0"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Now it&amp;#39;s time for &lt;a href="/dev-club/dev-onboarding/w/documentation/676/customization-for-product-devs"&gt;Customizations&lt;/a&gt;.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Integrations for Product Devs</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs/revision/7</link><pubDate>Mon, 24 Jun 2024 12:33:32 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:e64c91c4-03e5-454f-bbd7-3beb25519ac3</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs#comments</comments><description>Revision 7 posted to Dev Tutorials by Rafael Fernandes on 6/24/2024 12:33:32 PM&lt;br /&gt;
&lt;table style="margin-left:auto;margin-right:auto;width:100%;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#approach"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#rest"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#common"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#performance"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="approach"&gt;&lt;/a&gt;Integration Approaches&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;The Sugar platform is extremely powerful, flexible, and allows for easy integration. This flexibility means that determining the&amp;nbsp;best approach for your use case scenario is the key to success.&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Push/Pull from Sugar via REST API&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="text-decoration:underline;"&gt;Recommended&lt;/span&gt; approach&lt;/li&gt;
&lt;li&gt;Developers have full control over integration&lt;/li&gt;
&lt;li&gt;Integration can be stopped and systems will continue to work&lt;/li&gt;
&lt;li&gt;Retry mechanism: Resume integrations at any time (identify deltas through &amp;quot;last_update_time&amp;quot; flags)&lt;/li&gt;
&lt;li&gt;The time delay from/to Sugar is minimal&lt;/li&gt;
&lt;li&gt;Sugar REST API offers almost everything you need,&amp;nbsp;and can be further extended via customization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push to Sugar, Sugar pushes to an external queue in realtime&lt;span&gt;&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar Events to trigger through Logic Hooks&lt;/li&gt;
&lt;li&gt;Requires&amp;nbsp;Logic Hooks (code customization) to be created and deployed&lt;/li&gt;
&lt;li&gt;Does not offer a &amp;quot;retry mechanism&amp;quot;, if a logic hook fails to deliver to a queue or contact an external system&lt;/li&gt;
&lt;li&gt;Synchronous in nature, requires a response from an external system&lt;/li&gt;
&lt;li&gt;Needs to handle dependencies manually (contact can only be created after account)&lt;/li&gt;
&lt;li&gt;Good to have a middleware/queue in front of Sugar to receive those event triggers to&amp;nbsp;reliably&amp;nbsp;manage peak loads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Realtime: Embed your app into Sugar&amp;nbsp;through &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/User_Interface/Dashlets/"&gt;Dashlets&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Simplest approach&lt;/li&gt;
&lt;li&gt;Often requires web user-based authentication&lt;/li&gt;
&lt;li&gt;All load/traffic goes directly to your system,&amp;nbsp;which makes your system the performance bottleneck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="rest"&gt;&lt;/a&gt;REST API Webservices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;Accessing your data when you want is good. Accessing your data however you want is better. &lt;/span&gt;&lt;span&gt;When you decide to build an integration with Sugar, you&amp;rsquo;ll need an easy way to access and interact with the data stored in Sugar. The REST (&lt;/span&gt;&lt;span&gt;representational state transfer)&lt;/span&gt;&lt;span&gt;&amp;nbsp;API (application programming interface) is perfect for this.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sugar REST API Overview
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Fully RESTfull (GET, POST, PUT, DELETE)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;OAuth2 token based&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;All fields and modules are available through the API automatically&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Metadata API provides everything you need to know about your Sugar instance.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Topics
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/new-tutorial-intro-to-the-sugar-rest-api"&gt;Intro to the Sugar REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/how-sugar-rest-api-versioning-works"&gt;How Sugar REST API versioning works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/"&gt;RestAPI Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/sugarcrm-cookbook---the-school-of-rest---part-1"&gt;School of REST blog series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/"&gt;REST APIs Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Extending_Endpoints/"&gt;How to add your own custom endpoints to the REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/API_Exceptions/"&gt;API Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Best_Practices/"&gt;Best practices when integrating and migrating Sugar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="common"&gt;&lt;/a&gt;Common&amp;nbsp;APIs&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;It is important to understand our most commonly used APIs and their functions within Sugar. Your integration might need data within Sugar&amp;#39;s module structure that could potentially change over time, so you can use Metadata for it as well as CRUD onto Sugar.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Metadata
&lt;ul&gt;
&lt;li&gt;Endpoint with current system&amp;#39;s structure&lt;/li&gt;
&lt;li&gt;Modules, fields, relationships, layouts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Use carefully, its payload can be MBs in size, cache as much as possible&lt;/li&gt;
&lt;li&gt;GET /metadata (use filters as much as possible)&lt;/li&gt;
&lt;li&gt;It does not retrieve labels for dropdowns, use language API to do so&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/3-tips-for-using-the-sugar-metadata-api"&gt;3 Tips for using the Sugar Metadata API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Language
&lt;ul&gt;
&lt;li&gt;Endpoint to retrieve labels&lt;/li&gt;
&lt;li&gt;Dropdown list values&lt;/li&gt;
&lt;li&gt;Any language-specific content&lt;/li&gt;
&lt;li&gt;GET /lang/&amp;lt;language_code&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CRUD (Create, Read, Update, Delete) records
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_GET"&gt;Read&lt;/a&gt;: &lt;code&gt;GET /&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/module_POST"&gt;Create&lt;/a&gt;: &lt;code&gt;POST /&amp;lt;module&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_PUT"&gt;Update&lt;/a&gt;: &lt;code&gt;PUT&amp;nbsp;&lt;span&gt;/&amp;lt;module&amp;gt;/:record&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_DELETE"&gt;Delete&lt;/a&gt;: &lt;code&gt;DELETE&amp;nbsp;/&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulefilter_POST"&gt;Filter&lt;/a&gt;: &lt;code&gt;POST /&amp;lt;module&amp;gt;/filter&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;You can use &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulefilter_GET"&gt;GET&lt;/a&gt; as well&lt;/li&gt;
&lt;li&gt;POST solves the issue when a query is too long and hits HTTP limits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecordlinklink_name_GET"&gt;Retrieve records related to another module&lt;/a&gt;:&amp;nbsp;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record/link/:link_name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/modulerecordlinklink_nameadd_record_listremote_id_POST"&gt;Creates a relationship to a pre-existing record:&lt;/a&gt;&lt;code&gt; POST /&amp;lt;module&amp;gt;/:record/link/:link_name/:remote_id&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="performance"&gt;&lt;/a&gt;Performance and Best Practices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/h1&gt;
&lt;div class="row"&gt;
&lt;div class="col-xs-12 col-md-9"&gt;
&lt;p&gt;As you deep dive into Sugar APIs,&amp;nbsp;you will see how easy it is to integrate to pull and push data from and to Sugar and your systems, however, you must consider performance so your integration doesn&amp;#39;t become a bottleneck between those systems.&lt;/p&gt;
&lt;p&gt;You should consider the following guidelines when implementing your integrations:&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar&amp;#39;s sync_key to link to remote IDs
&lt;ul&gt;
&lt;li&gt;Sugar provides in every module a sync_key field&lt;/li&gt;
&lt;li&gt;sync_key is a unique identifier for that module that links back to your external system&amp;#39;s generated key&lt;/li&gt;
&lt;li&gt;For example, account ID from ERP is AC0001, set sync_key (pass as a parameter in the POST) and sugar will create a record in account with sync_key=AC0001&lt;/li&gt;
&lt;li&gt;Next patch/update, sugar will check &amp;quot;where sync_key=&amp;#39;AC0001&amp;#39;&amp;quot; and update it (it is indexed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Integrate Upsert APIs
&lt;ul&gt;
&lt;li&gt;Sugar&amp;#39;s &amp;quot;update or insert&amp;quot; API based on sync_key&lt;/li&gt;
&lt;li&gt;Simplifies a common operation - if record exists, update it, otherwise create it (GET followed by a&amp;nbsp;PUT or POST)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_PATCH"&gt;Upsert by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_GET"&gt;Get by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_DELETE"&gt;Delete by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulerecord_idsync_key_field_namesync_key_field_value_PATCH"&gt;Set a sync on existing record (without sync_key)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_POST"&gt;Create relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_DELETE"&gt;Delete relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Bulk API
&lt;ul&gt;
&lt;li&gt;An endpoint that encapsulates multiple API calls into one single HTTP request&lt;/li&gt;
&lt;li&gt;Requests are executed synchronously (one after the other)&lt;/li&gt;
&lt;li&gt;Reducing network latency between calls&lt;/li&gt;
&lt;li&gt;Combined with Upsert provides the best performance&lt;/li&gt;
&lt;li&gt;Careful not to add too many requests to it&lt;/li&gt;
&lt;li&gt;Start small (5 to 10 requests) and increase until you reach its max capacity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Polling and filtering time-based with Filter API
&lt;ul&gt;
&lt;li&gt;Integration gateway (or your external system) asks Sugar every X minutes&lt;/li&gt;
&lt;li&gt;Request Filter API using &lt;code&gt;max_num&lt;/code&gt; (max number of records), offset and fields&lt;/li&gt;
&lt;li&gt;The response will provide the data as well as &lt;code&gt;next_offset&lt;/code&gt; (offset can be seen as pagination)&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;next_offset&lt;/code&gt; is -1, no more records to go through&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Initial Data Load into Sugar&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Use Bulk + Upsert to achieve data loads&lt;/li&gt;
&lt;li&gt;Millions&amp;nbsp;of records may take a little while to process, plan ahead (over the weekend)&lt;/li&gt;
&lt;li&gt;Use multi-thread processes to load (for example 20 threads sending 20 bulk upsert requests)&lt;/li&gt;
&lt;li&gt;Careful with&amp;nbsp;&lt;a href="https://support.sugarcrm.com/Resources/Sugar_Cloud_Policy_Guide/#Rate_Limits"&gt;Sugar Cloud rate limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&amp;#39;s always a good idea to let Sugar Support know you&amp;#39;re data loading, they will be considerate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Understanding PHP limitations&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;PHP is single-threaded with limited resources to process your request&lt;/li&gt;
&lt;li&gt;If you send too much data using bulk, you may run out of memory for that request&lt;/li&gt;
&lt;li&gt;Push to the limits but give some room for PHP to finish the request gracefully&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Pagination for millions of records by using OFFSET will degrade performance
&lt;ul&gt;
&lt;li&gt;We rely on DB to find, sort and limit records&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/swlh/sql-pagination-you-are-probably-doing-it-wrong-d0f2719cc166"&gt;Nice article &lt;/a&gt;explaining how this works in details&lt;/li&gt;
&lt;li&gt;Instead of offsets, store the last processed ID and use it in the WHERE clause and sort by ID&lt;/li&gt;
&lt;li&gt;Example
&lt;ul&gt;
&lt;li&gt;Instead of: (/v11_25/Leads?max_num=1000&amp;amp;&lt;strong&gt;offset=4619000&lt;/strong&gt;&amp;amp;order_by=id)&lt;/li&gt;
&lt;li&gt;Do this&amp;nbsp;(/v11_25/Leads?&lt;strong&gt;filter=[{"id":&amp;rdquo;&amp;lt;last_id&amp;gt;"}]&lt;/strong&gt;&amp;amp;max_num=1000&amp;amp;order_by=id)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If you need to add a date, make sure to add it as part of the filter and order&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p id="mcetoc_1f5uvkqns0"&gt;&lt;span style="font-size:150%;"&gt;You&amp;#39;re up and running, but don&amp;#39;t stop now - this is just the beginning of your journey. &lt;/span&gt;&lt;/p&gt;
&lt;p id="mcetoc_1g9jl704d0"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Now it&amp;#39;s time for &lt;a href="/dev-club/dev-onboarding/w/documentation/676/customization-for-product-devs"&gt;Customizations&lt;/a&gt;.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Integrations for Product Devs</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs/revision/6</link><pubDate>Tue, 25 Apr 2023 14:23:47 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:e64c91c4-03e5-454f-bbd7-3beb25519ac3</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs#comments</comments><description>Revision 6 posted to Dev Tutorials by Rafael Fernandes on 4/25/2023 2:23:47 PM&lt;br /&gt;
&lt;table style="margin-left:auto;margin-right:auto;width:100%;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#approach"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#rest"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#common"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#performance"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="approach"&gt;&lt;/a&gt;Integration Approaches&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;The Sugar platform is extremely powerful, flexible, and allows for easy integration. This flexibility means that determining the&amp;nbsp;best approach for your use case scenario is the key to success.&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Push/Pull from Sugar via REST API&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="text-decoration:underline;"&gt;Recommended&lt;/span&gt; approach&lt;/li&gt;
&lt;li&gt;Developers have full control over integration&lt;/li&gt;
&lt;li&gt;Integration can be stopped and systems will continue to work&lt;/li&gt;
&lt;li&gt;Retry mechanism: Resume integrations at any time (identify deltas through &amp;quot;last_update_time&amp;quot; flags)&lt;/li&gt;
&lt;li&gt;The time delay from/to Sugar is minimal&lt;/li&gt;
&lt;li&gt;Sugar REST API offers almost everything you need,&amp;nbsp;and can be further extended via customization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push to Sugar, Sugar pushes to an external queue in realtime&lt;span&gt;&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar Events to trigger through Logic Hooks&lt;/li&gt;
&lt;li&gt;Requires&amp;nbsp;Logic Hooks (code customization) to be created and deployed&lt;/li&gt;
&lt;li&gt;Does not offer a &amp;quot;retry mechanism&amp;quot;, if a logic hook fails to deliver to a queue or contact an external system&lt;/li&gt;
&lt;li&gt;Synchronous in nature, requires a response from an external system&lt;/li&gt;
&lt;li&gt;Needs to handle dependencies manually (contact can only be created after account)&lt;/li&gt;
&lt;li&gt;Good to have a middleware/queue in front of Sugar to receive those event triggers to&amp;nbsp;reliably&amp;nbsp;manage peak loads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Realtime: Embed your app into Sugar&amp;nbsp;through &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/User_Interface/Dashlets/"&gt;Dashlets&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Simplest approach&lt;/li&gt;
&lt;li&gt;Often requires web user-based authentication&lt;/li&gt;
&lt;li&gt;All load/traffic goes directly to your system,&amp;nbsp;which makes your system the performance bottleneck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="rest"&gt;&lt;/a&gt;REST API Webservices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;Accessing your data when you want is good. Accessing your data however you want is better. &lt;/span&gt;&lt;span&gt;When you decide to build an integration with Sugar, you&amp;rsquo;ll need an easy way to access and interact with the data stored in Sugar. The REST (&lt;/span&gt;&lt;span&gt;representational state transfer)&lt;/span&gt;&lt;span&gt;&amp;nbsp;API (application programming interface) is perfect for this.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sugar REST API Overview
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Fully RESTfull (GET, POST, PUT, DELETE)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;OAuth2 token based&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;All fields and modules are available through the API automatically&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Metadata API provides everything you need to know about your Sugar instance.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Topics
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/new-tutorial-intro-to-the-sugar-rest-api"&gt;Intro to the Sugar REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/how-sugar-rest-api-versioning-works"&gt;How Sugar REST API versioning works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/"&gt;RestAPI Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/sugarcrm-cookbook---the-school-of-rest---part-1"&gt;School of REST blog series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/"&gt;REST APIs Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Extending_Endpoints/"&gt;How to add your own custom endpoints to the REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/API_Exceptions/"&gt;API Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Best_Practices/"&gt;Best practices when integrating and migrating Sugar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="common"&gt;&lt;/a&gt;Common&amp;nbsp;APIs&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;It is important to understand our most commonly used APIs and their functions within Sugar. Your integration might need data within Sugar&amp;#39;s module structure that could potentially change over time, so you can use Metadata for it as well as CRUD onto Sugar.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Metadata
&lt;ul&gt;
&lt;li&gt;Endpoint with current system&amp;#39;s structure&lt;/li&gt;
&lt;li&gt;Modules, fields, relationships, layouts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Use carefully, its payload can be MBs in size, cache as much as possible&lt;/li&gt;
&lt;li&gt;GET /metadata (use filters as much as possible)&lt;/li&gt;
&lt;li&gt;It does not retrieve labels for dropdowns, use language API to do so&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/3-tips-for-using-the-sugar-metadata-api"&gt;3 Tips for using the Sugar Metadata API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Language
&lt;ul&gt;
&lt;li&gt;Endpoint to retrieve labels&lt;/li&gt;
&lt;li&gt;Dropdown list values&lt;/li&gt;
&lt;li&gt;Any language-specific content&lt;/li&gt;
&lt;li&gt;GET /lang/&amp;lt;language_code&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CRUD (Create, Read, Update, Delete) records
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_GET"&gt;Read&lt;/a&gt;: &lt;code&gt;GET /&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/module_POST"&gt;Create&lt;/a&gt;: &lt;code&gt;POST /&amp;lt;module&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_PUT"&gt;Update&lt;/a&gt;: &lt;code&gt;PUT&amp;nbsp;&lt;span&gt;/&amp;lt;module&amp;gt;/:record&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_DELETE"&gt;Delete&lt;/a&gt;: &lt;code&gt;DELETE&amp;nbsp;/&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulefilter_POST"&gt;Filter&lt;/a&gt;: &lt;code&gt;POST /&amp;lt;module&amp;gt;/filter&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;You can use &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulefilter_GET"&gt;GET&lt;/a&gt; as well&lt;/li&gt;
&lt;li&gt;POST solves the issue when a query is too long and hits HTTP limits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecordlinklink_name_GET"&gt;Retrieve records related to another module&lt;/a&gt;:&amp;nbsp;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record/link/:link_name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/modulerecordlinklink_nameadd_record_listremote_id_POST"&gt;Creates a relationship to a pre-existing record:&lt;/a&gt;&lt;code&gt; POST /&amp;lt;module&amp;gt;/:record/link/:link_name/:remote_id&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="performance"&gt;&lt;/a&gt;Performance and Best Practices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/h1&gt;
&lt;div class="row"&gt;
&lt;div class="col-xs-12 col-md-9"&gt;
&lt;p&gt;As you deep dive into Sugar APIs,&amp;nbsp;you will see how easy it is to integrate to pull and push data from and to Sugar and your systems, however, you must consider performance so your integration doesn&amp;#39;t become a bottleneck between those systems.&lt;/p&gt;
&lt;p&gt;You should consider the following guidelines when implementing your integrations:&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar&amp;#39;s sync_key to link to remote IDs
&lt;ul&gt;
&lt;li&gt;Sugar provides in every module a sync_key field&lt;/li&gt;
&lt;li&gt;sync_key is a unique identifier for that module that links back to your external system&amp;#39;s generated key&lt;/li&gt;
&lt;li&gt;For example, account ID from ERP is AC0001, set sync_key (pass as a parameter in the POST) and sugar will create a record in account with sync_key=AC0001&lt;/li&gt;
&lt;li&gt;Next patch/update, sugar will check &amp;quot;where sync_key=&amp;#39;AC0001&amp;#39;&amp;quot; and update it (it is indexed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Integrate Upsert APIs
&lt;ul&gt;
&lt;li&gt;Sugar&amp;#39;s &amp;quot;update or insert&amp;quot; API based on sync_key&lt;/li&gt;
&lt;li&gt;Simplifies a common operation - if record exists, update it, otherwise create it (GET followed by a&amp;nbsp;PUT or POST)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_PATCH"&gt;Upsert by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_GET"&gt;Get by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_DELETE"&gt;Delete by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulerecord_idsync_key_field_namesync_key_field_value_PATCH"&gt;Set a sync on existing record (without sync_key)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_POST"&gt;Create relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_DELETE"&gt;Delete relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Bulk API
&lt;ul&gt;
&lt;li&gt;An endpoint that encapsulates multiple API calls into one single HTTP request&lt;/li&gt;
&lt;li&gt;Requests are executed synchronously (one after the other)&lt;/li&gt;
&lt;li&gt;Reducing network latency between calls&lt;/li&gt;
&lt;li&gt;Combined with Upsert provides the best performance&lt;/li&gt;
&lt;li&gt;Careful not to add too many requests to it&lt;/li&gt;
&lt;li&gt;Start small (5 to 10 requests) and increase until you reach its max capacity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Polling and filtering time-based with Filter API
&lt;ul&gt;
&lt;li&gt;Integration gateway (or your external system) asks Sugar every X minutes&lt;/li&gt;
&lt;li&gt;Request Filter API using &lt;code&gt;max_num&lt;/code&gt; (max number of records), offset and fields&lt;/li&gt;
&lt;li&gt;The response will provide the data as well as &lt;code&gt;next_offset&lt;/code&gt; (offset can be seen as pagination)&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;next_offset&lt;/code&gt; is -1, no more records to go through&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Initial Data Load into Sugar&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Use Bulk + Upsert to achieve data loads&lt;/li&gt;
&lt;li&gt;Millions&amp;nbsp;of records may take a little while to process, plan ahead (over the weekend)&lt;/li&gt;
&lt;li&gt;Use multi-thread processes to load (for example 20 threads sending 20 bulk upsert requests)&lt;/li&gt;
&lt;li&gt;Careful with&amp;nbsp;&lt;a href="https://support.sugarcrm.com/Resources/Sugar_Cloud_Policy_Guide/#Rate_Limits"&gt;Sugar Cloud rate limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&amp;#39;s always a good idea to let Sugar Support know you&amp;#39;re data loading, they will be considerate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Understanding PHP limitations&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;PHP is single-threaded with limited resources to process your request&lt;/li&gt;
&lt;li&gt;If you send too much data using bulk, you may run out of memory for that request&lt;/li&gt;
&lt;li&gt;Push to the limits but give some room for PHP to finish the request gracefully&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p id="mcetoc_1f5uvkqns0"&gt;&lt;span style="font-size:150%;"&gt;You&amp;#39;re up and running, but don&amp;#39;t stop now - this is just the beginning of your journey. &lt;/span&gt;&lt;/p&gt;
&lt;p id="mcetoc_1g9jl704d0"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Now it&amp;#39;s time for &lt;a href="/dev-club/dev-onboarding/w/documentation/676/customization-for-product-devs"&gt;Customizations&lt;/a&gt;.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Integrations for Product Devs</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs/revision/4</link><pubDate>Thu, 04 Aug 2022 05:31:46 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:e64c91c4-03e5-454f-bbd7-3beb25519ac3</guid><dc:creator>Alex Nassi</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs#comments</comments><description>Revision 4 posted to Dev Tutorials by Alex Nassi on 8/4/2022 5:31:46 AM&lt;br /&gt;
&lt;table style="margin-left:auto;margin-right:auto;width:100%;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#approach"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/1.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#rest"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/7612.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#common"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/3.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#performance"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/4.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="approach"&gt;&lt;/a&gt;Integration Approaches&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/1.png" /&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;The Sugar platform is extremely powerful, flexible, and allows for easy integration. This flexibility means that determining the&amp;nbsp;best approach for your use case scenario is the key to success.&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Push/Pull from Sugar via REST API&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="text-decoration:underline;"&gt;Recommended&lt;/span&gt; approach&lt;/li&gt;
&lt;li&gt;Developers have full control over integration&lt;/li&gt;
&lt;li&gt;Integration can be stopped and systems will continue to work&lt;/li&gt;
&lt;li&gt;Retry mechanism: Resume integrations at any time (identify deltas through &amp;quot;last_update_time&amp;quot; flags)&lt;/li&gt;
&lt;li&gt;The time delay from/to Sugar is minimal&lt;/li&gt;
&lt;li&gt;Sugar REST API offers almost everything you need,&amp;nbsp;and can be further extended via customization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push to Sugar, Sugar pushes to an external queue in realtime&lt;span&gt;&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar Events to trigger through Logic Hooks&lt;/li&gt;
&lt;li&gt;Requires&amp;nbsp;Logic Hooks (code customization) to be created and deployed&lt;/li&gt;
&lt;li&gt;Does not offer a &amp;quot;retry mechanism&amp;quot;, if a logic hook fails to deliver to a queue or contact an external system&lt;/li&gt;
&lt;li&gt;Synchronous in nature, requires a response from an external system&lt;/li&gt;
&lt;li&gt;Needs to handle dependencies manually (contact can only be created after account)&lt;/li&gt;
&lt;li&gt;Good to have a middleware/queue in front of Sugar to receive those event triggers to&amp;nbsp;reliably&amp;nbsp;manage peak loads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Realtime: Embed your app into Sugar&amp;nbsp;through &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/User_Interface/Dashlets/"&gt;Dashlets&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Simplest approach&lt;/li&gt;
&lt;li&gt;Often requires web user-based authentication&lt;/li&gt;
&lt;li&gt;All load/traffic goes directly to your system,&amp;nbsp;which makes your system the performance bottleneck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="rest"&gt;&lt;/a&gt;REST API Webservices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/7612.png" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;Accessing your data when you want is good. Accessing your data however you want is better. &lt;/span&gt;&lt;span&gt;When you decide to build an integration with Sugar, you&amp;rsquo;ll need an easy way to access and interact with the data stored in Sugar. The REST (&lt;/span&gt;&lt;span&gt;representational state transfer)&lt;/span&gt;&lt;span&gt;&amp;nbsp;API (application programming interface) is perfect for this.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sugar REST API Overview
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Fully RESTfull (GET, POST, PUT, DELETE)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;OAuth2 token based&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;All fields and modules are available through the API automatically&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Metadata API provides everything you need to know about your Sugar instance.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Topics
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/new-tutorial-intro-to-the-sugar-rest-api"&gt;Intro to the Sugar REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/how-sugar-rest-api-versioning-works"&gt;How Sugar REST API versioning works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/"&gt;RestAPI Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/sugarcrm-cookbook---the-school-of-rest---part-1"&gt;School of REST blog series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/"&gt;REST APIs Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Extending_Endpoints/"&gt;How to add your own custom endpoints to the REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/API_Exceptions/"&gt;API Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Best_Practices/"&gt;Best practices when integrating and migrating Sugar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="common"&gt;&lt;/a&gt;Common&amp;nbsp;APIs&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/3.png" /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;It is important to understand our most commonly used APIs and their functions within Sugar. Your integration might need data within Sugar&amp;#39;s module structure that could potentially change over time, so you can use Metadata for it as well as CRUD onto Sugar.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Metadata
&lt;ul&gt;
&lt;li&gt;Endpoint with current system&amp;#39;s structure&lt;/li&gt;
&lt;li&gt;Modules, fields, relationships, layouts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Use carefully, its payload can be MBs in size, cache as much as possible&lt;/li&gt;
&lt;li&gt;GET /metadata (use filters as much as possible)&lt;/li&gt;
&lt;li&gt;It does not retrieve labels for dropdowns, use language API to do so&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/3-tips-for-using-the-sugar-metadata-api"&gt;3 Tips for using the Sugar Metadata API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Language
&lt;ul&gt;
&lt;li&gt;Endpoint to retrieve labels&lt;/li&gt;
&lt;li&gt;Dropdown list values&lt;/li&gt;
&lt;li&gt;Any language-specific content&lt;/li&gt;
&lt;li&gt;GET /lang/&amp;lt;language_code&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CRUD (Create, Read, Update, Delete) records
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_GET"&gt;Read&lt;/a&gt;: &lt;code&gt;GET /&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/module_POST"&gt;Create&lt;/a&gt;: &lt;code&gt;POST /&amp;lt;module&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_PUT"&gt;Update&lt;/a&gt;: &lt;code&gt;PUT&amp;nbsp;&lt;span&gt;/&amp;lt;module&amp;gt;/:record&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_DELETE"&gt;Delete&lt;/a&gt;: &lt;code&gt;DELETE&amp;nbsp;/&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulefilter_POST"&gt;Filter&lt;/a&gt;: &lt;code&gt;POST /&amp;lt;module&amp;gt;/filter&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;You can use &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulefilter_GET"&gt;GET&lt;/a&gt; as well&lt;/li&gt;
&lt;li&gt;POST solves the issue when a query is too long and hits HTTP limits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecordlinklink_name_GET"&gt;Retrieve records related to another module&lt;/a&gt;:&amp;nbsp;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record/link/:link_name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecordlinklink_nameremote_id_POST"&gt;Creates a relationship to a pre-existing record:&lt;/a&gt;&lt;code&gt; POST /&amp;lt;module&amp;gt;/:record/link/:link_name/:remote_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="performance"&gt;&lt;/a&gt;Performance and Best Practices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/4.png" /&gt;&lt;/h1&gt;
&lt;div class="row"&gt;
&lt;div class="col-xs-12 col-md-9"&gt;
&lt;p&gt;As you deep dive into Sugar APIs,&amp;nbsp;you will see how easy it is to integrate to pull and push data from and to Sugar and your systems, however, you must consider performance so your integration doesn&amp;#39;t become a bottleneck between those systems.&lt;/p&gt;
&lt;p&gt;You should consider the following guidelines when implementing your integrations:&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar&amp;#39;s sync_key to link to remote IDs
&lt;ul&gt;
&lt;li&gt;Sugar provides in every module a sync_key field&lt;/li&gt;
&lt;li&gt;sync_key is a unique identifier for that module that links back to your external system&amp;#39;s generated key&lt;/li&gt;
&lt;li&gt;For example, account ID from ERP is AC0001, set sync_key (pass as a parameter in the POST) and sugar will create a record in account with sync_key=AC0001&lt;/li&gt;
&lt;li&gt;Next patch/update, sugar will check &amp;quot;where sync_key=&amp;#39;AC0001&amp;#39;&amp;quot; and update it (it is indexed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Integrate Upsert APIs
&lt;ul&gt;
&lt;li&gt;Sugar&amp;#39;s &amp;quot;update or insert&amp;quot; API based on sync_key&lt;/li&gt;
&lt;li&gt;Simplifies a common operation - if record exists, update it, otherwise create it (GET followed by a&amp;nbsp;PUT or POST)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_PATCH"&gt;Upsert by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_GET"&gt;Get by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_DELETE"&gt;Delete by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulerecord_idsync_key_field_namesync_key_field_value_PATCH"&gt;Set a sync on existing record (without sync_key)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_POST"&gt;Create relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_DELETE"&gt;Delete relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Bulk API
&lt;ul&gt;
&lt;li&gt;An endpoint that encapsulates multiple API calls into one single HTTP request&lt;/li&gt;
&lt;li&gt;Requests are executed synchronously (one after the other)&lt;/li&gt;
&lt;li&gt;Reducing network latency between calls&lt;/li&gt;
&lt;li&gt;Combined with Upsert provides the best performance&lt;/li&gt;
&lt;li&gt;Careful not to add too many requests to it&lt;/li&gt;
&lt;li&gt;Start small (5 to 10 requests) and increase until you reach its max capacity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Polling and filtering time-based with Filter API
&lt;ul&gt;
&lt;li&gt;Integration gateway (or your external system) asks Sugar every X minutes&lt;/li&gt;
&lt;li&gt;Request Filter API using &lt;code&gt;max_num&lt;/code&gt; (max number of records), offset and fields&lt;/li&gt;
&lt;li&gt;The response will provide the data as well as &lt;code&gt;next_offset&lt;/code&gt; (offset can be seen as pagination)&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;next_offset&lt;/code&gt; is -1, no more records to go through&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Initial Data Load into Sugar&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Use Bulk + Upsert to achieve data loads&lt;/li&gt;
&lt;li&gt;Millions&amp;nbsp;of records may take a little while to process, plan ahead (over the weekend)&lt;/li&gt;
&lt;li&gt;Use multi-thread processes to load (for example 20 threads sending 20 bulk upsert requests)&lt;/li&gt;
&lt;li&gt;Careful with&amp;nbsp;&lt;a href="https://support.sugarcrm.com/Resources/Sugar_Cloud_Policy_Guide/#Rate_Limits"&gt;Sugar Cloud rate limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&amp;#39;s always a good idea to let Sugar Support know you&amp;#39;re data loading, they will be considerate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Understanding PHP limitations&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;PHP is single-threaded with limited resources to process your request&lt;/li&gt;
&lt;li&gt;If you send too much data using bulk, you may run out of memory for that request&lt;/li&gt;
&lt;li&gt;Push to the limits but give some room for PHP to finish the request gracefully&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p id="mcetoc_1f5uvkqns0"&gt;&lt;span style="font-size:150%;"&gt;You&amp;#39;re up and running, but don&amp;#39;t stop now - this is just the beginning of your journey. &lt;/span&gt;&lt;/p&gt;
&lt;p id="mcetoc_1g9jl704d0"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Now it&amp;#39;s time for &lt;a href="/dev-club/dev-onboarding/w/documentation/676/customization-for-product-devs"&gt;Customizations&lt;/a&gt;.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Integrations for Product Devs</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs/revision/5</link><pubDate>Thu, 04 Aug 2022 05:31:46 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:e64c91c4-03e5-454f-bbd7-3beb25519ac3</guid><dc:creator>Alex Nassi</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs#comments</comments><description>Revision 5 posted to Dev Tutorials by Alex Nassi on 8/4/2022 5:31:46 AM&lt;br /&gt;
&lt;table style="margin-left:auto;margin-right:auto;width:100%;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#approach"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#rest"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#common"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#performance"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="approach"&gt;&lt;/a&gt;Integration Approaches&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/1.png" /&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;The Sugar platform is extremely powerful, flexible, and allows for easy integration. This flexibility means that determining the&amp;nbsp;best approach for your use case scenario is the key to success.&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Push/Pull from Sugar via REST API&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="text-decoration:underline;"&gt;Recommended&lt;/span&gt; approach&lt;/li&gt;
&lt;li&gt;Developers have full control over integration&lt;/li&gt;
&lt;li&gt;Integration can be stopped and systems will continue to work&lt;/li&gt;
&lt;li&gt;Retry mechanism: Resume integrations at any time (identify deltas through &amp;quot;last_update_time&amp;quot; flags)&lt;/li&gt;
&lt;li&gt;The time delay from/to Sugar is minimal&lt;/li&gt;
&lt;li&gt;Sugar REST API offers almost everything you need,&amp;nbsp;and can be further extended via customization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push to Sugar, Sugar pushes to an external queue in realtime&lt;span&gt;&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar Events to trigger through Logic Hooks&lt;/li&gt;
&lt;li&gt;Requires&amp;nbsp;Logic Hooks (code customization) to be created and deployed&lt;/li&gt;
&lt;li&gt;Does not offer a &amp;quot;retry mechanism&amp;quot;, if a logic hook fails to deliver to a queue or contact an external system&lt;/li&gt;
&lt;li&gt;Synchronous in nature, requires a response from an external system&lt;/li&gt;
&lt;li&gt;Needs to handle dependencies manually (contact can only be created after account)&lt;/li&gt;
&lt;li&gt;Good to have a middleware/queue in front of Sugar to receive those event triggers to&amp;nbsp;reliably&amp;nbsp;manage peak loads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Realtime: Embed your app into Sugar&amp;nbsp;through &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/User_Interface/Dashlets/"&gt;Dashlets&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Simplest approach&lt;/li&gt;
&lt;li&gt;Often requires web user-based authentication&lt;/li&gt;
&lt;li&gt;All load/traffic goes directly to your system,&amp;nbsp;which makes your system the performance bottleneck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="rest"&gt;&lt;/a&gt;REST API Webservices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/7612.png" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;Accessing your data when you want is good. Accessing your data however you want is better. &lt;/span&gt;&lt;span&gt;When you decide to build an integration with Sugar, you&amp;rsquo;ll need an easy way to access and interact with the data stored in Sugar. The REST (&lt;/span&gt;&lt;span&gt;representational state transfer)&lt;/span&gt;&lt;span&gt;&amp;nbsp;API (application programming interface) is perfect for this.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sugar REST API Overview
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Fully RESTfull (GET, POST, PUT, DELETE)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;OAuth2 token based&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;All fields and modules are available through the API automatically&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Metadata API provides everything you need to know about your Sugar instance.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Topics
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/new-tutorial-intro-to-the-sugar-rest-api"&gt;Intro to the Sugar REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/how-sugar-rest-api-versioning-works"&gt;How Sugar REST API versioning works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/"&gt;RestAPI Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/sugarcrm-cookbook---the-school-of-rest---part-1"&gt;School of REST blog series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/"&gt;REST APIs Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Extending_Endpoints/"&gt;How to add your own custom endpoints to the REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/API_Exceptions/"&gt;API Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Best_Practices/"&gt;Best practices when integrating and migrating Sugar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="common"&gt;&lt;/a&gt;Common&amp;nbsp;APIs&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/3.png" /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;It is important to understand our most commonly used APIs and their functions within Sugar. Your integration might need data within Sugar&amp;#39;s module structure that could potentially change over time, so you can use Metadata for it as well as CRUD onto Sugar.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Metadata
&lt;ul&gt;
&lt;li&gt;Endpoint with current system&amp;#39;s structure&lt;/li&gt;
&lt;li&gt;Modules, fields, relationships, layouts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Use carefully, its payload can be MBs in size, cache as much as possible&lt;/li&gt;
&lt;li&gt;GET /metadata (use filters as much as possible)&lt;/li&gt;
&lt;li&gt;It does not retrieve labels for dropdowns, use language API to do so&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/3-tips-for-using-the-sugar-metadata-api"&gt;3 Tips for using the Sugar Metadata API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Language
&lt;ul&gt;
&lt;li&gt;Endpoint to retrieve labels&lt;/li&gt;
&lt;li&gt;Dropdown list values&lt;/li&gt;
&lt;li&gt;Any language-specific content&lt;/li&gt;
&lt;li&gt;GET /lang/&amp;lt;language_code&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CRUD (Create, Read, Update, Delete) records
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_GET"&gt;Read&lt;/a&gt;: &lt;code&gt;GET /&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/module_POST"&gt;Create&lt;/a&gt;: &lt;code&gt;POST /&amp;lt;module&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_PUT"&gt;Update&lt;/a&gt;: &lt;code&gt;PUT&amp;nbsp;&lt;span&gt;/&amp;lt;module&amp;gt;/:record&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_DELETE"&gt;Delete&lt;/a&gt;: &lt;code&gt;DELETE&amp;nbsp;/&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulefilter_POST"&gt;Filter&lt;/a&gt;: &lt;code&gt;POST /&amp;lt;module&amp;gt;/filter&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;You can use &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulefilter_GET"&gt;GET&lt;/a&gt; as well&lt;/li&gt;
&lt;li&gt;POST solves the issue when a query is too long and hits HTTP limits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecordlinklink_name_GET"&gt;Retrieve records related to another module&lt;/a&gt;:&amp;nbsp;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record/link/:link_name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecordlinklink_nameremote_id_POST"&gt;Creates a relationship to a pre-existing record:&lt;/a&gt;&lt;code&gt; POST /&amp;lt;module&amp;gt;/:record/link/:link_name/:remote_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="performance"&gt;&lt;/a&gt;Performance and Best Practices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-14/4.png" /&gt;&lt;/h1&gt;
&lt;div class="row"&gt;
&lt;div class="col-xs-12 col-md-9"&gt;
&lt;p&gt;As you deep dive into Sugar APIs,&amp;nbsp;you will see how easy it is to integrate to pull and push data from and to Sugar and your systems, however, you must consider performance so your integration doesn&amp;#39;t become a bottleneck between those systems.&lt;/p&gt;
&lt;p&gt;You should consider the following guidelines when implementing your integrations:&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar&amp;#39;s sync_key to link to remote IDs
&lt;ul&gt;
&lt;li&gt;Sugar provides in every module a sync_key field&lt;/li&gt;
&lt;li&gt;sync_key is a unique identifier for that module that links back to your external system&amp;#39;s generated key&lt;/li&gt;
&lt;li&gt;For example, account ID from ERP is AC0001, set sync_key (pass as a parameter in the POST) and sugar will create a record in account with sync_key=AC0001&lt;/li&gt;
&lt;li&gt;Next patch/update, sugar will check &amp;quot;where sync_key=&amp;#39;AC0001&amp;#39;&amp;quot; and update it (it is indexed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Integrate Upsert APIs
&lt;ul&gt;
&lt;li&gt;Sugar&amp;#39;s &amp;quot;update or insert&amp;quot; API based on sync_key&lt;/li&gt;
&lt;li&gt;Simplifies a common operation - if record exists, update it, otherwise create it (GET followed by a&amp;nbsp;PUT or POST)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_PATCH"&gt;Upsert by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_GET"&gt;Get by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_DELETE"&gt;Delete by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulerecord_idsync_key_field_namesync_key_field_value_PATCH"&gt;Set a sync on existing record (without sync_key)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_POST"&gt;Create relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_DELETE"&gt;Delete relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Bulk API
&lt;ul&gt;
&lt;li&gt;An endpoint that encapsulates multiple API calls into one single HTTP request&lt;/li&gt;
&lt;li&gt;Requests are executed synchronously (one after the other)&lt;/li&gt;
&lt;li&gt;Reducing network latency between calls&lt;/li&gt;
&lt;li&gt;Combined with Upsert provides the best performance&lt;/li&gt;
&lt;li&gt;Careful not to add too many requests to it&lt;/li&gt;
&lt;li&gt;Start small (5 to 10 requests) and increase until you reach its max capacity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Polling and filtering time-based with Filter API
&lt;ul&gt;
&lt;li&gt;Integration gateway (or your external system) asks Sugar every X minutes&lt;/li&gt;
&lt;li&gt;Request Filter API using &lt;code&gt;max_num&lt;/code&gt; (max number of records), offset and fields&lt;/li&gt;
&lt;li&gt;The response will provide the data as well as &lt;code&gt;next_offset&lt;/code&gt; (offset can be seen as pagination)&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;next_offset&lt;/code&gt; is -1, no more records to go through&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Initial Data Load into Sugar&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Use Bulk + Upsert to achieve data loads&lt;/li&gt;
&lt;li&gt;Millions&amp;nbsp;of records may take a little while to process, plan ahead (over the weekend)&lt;/li&gt;
&lt;li&gt;Use multi-thread processes to load (for example 20 threads sending 20 bulk upsert requests)&lt;/li&gt;
&lt;li&gt;Careful with&amp;nbsp;&lt;a href="https://support.sugarcrm.com/Resources/Sugar_Cloud_Policy_Guide/#Rate_Limits"&gt;Sugar Cloud rate limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&amp;#39;s always a good idea to let Sugar Support know you&amp;#39;re data loading, they will be considerate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Understanding PHP limitations&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;PHP is single-threaded with limited resources to process your request&lt;/li&gt;
&lt;li&gt;If you send too much data using bulk, you may run out of memory for that request&lt;/li&gt;
&lt;li&gt;Push to the limits but give some room for PHP to finish the request gracefully&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p id="mcetoc_1f5uvkqns0"&gt;&lt;span style="font-size:150%;"&gt;You&amp;#39;re up and running, but don&amp;#39;t stop now - this is just the beginning of your journey. &lt;/span&gt;&lt;/p&gt;
&lt;p id="mcetoc_1g9jl704d0"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Now it&amp;#39;s time for &lt;a href="/dev-club/dev-onboarding/w/documentation/676/customization-for-product-devs"&gt;Customizations&lt;/a&gt;.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Integrations for Product Devs</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs/revision/3</link><pubDate>Thu, 04 Aug 2022 05:31:09 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:e64c91c4-03e5-454f-bbd7-3beb25519ac3</guid><dc:creator>Alex Nassi</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs#comments</comments><description>Revision 3 posted to Dev Tutorials by Alex Nassi on 8/4/2022 5:31:09 AM&lt;br /&gt;
&lt;table style="margin-left:auto;margin-right:auto;width:100%;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#approach"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/1.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/7612.png" /&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#common"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/3.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#performance"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/4.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="approach"&gt;&lt;/a&gt;Integration Approaches&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/1.png" /&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;The Sugar platform is extremely powerful, flexible, and allows for easy integration. This flexibility means that determining the&amp;nbsp;best approach for your use case scenario is the key to success.&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Push/Pull from Sugar via REST API&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="text-decoration:underline;"&gt;Recommended&lt;/span&gt; approach&lt;/li&gt;
&lt;li&gt;Developers have full control over integration&lt;/li&gt;
&lt;li&gt;Integration can be stopped and systems will continue to work&lt;/li&gt;
&lt;li&gt;Retry mechanism: Resume integrations at any time (identify deltas through &amp;quot;last_update_time&amp;quot; flags)&lt;/li&gt;
&lt;li&gt;The time delay from/to Sugar is minimal&lt;/li&gt;
&lt;li&gt;Sugar REST API offers almost everything you need,&amp;nbsp;and can be further extended via customization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push to Sugar, Sugar pushes to an external queue in realtime&lt;span&gt;&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar Events to trigger through Logic Hooks&lt;/li&gt;
&lt;li&gt;Requires&amp;nbsp;Logic Hooks (code customization) to be created and deployed&lt;/li&gt;
&lt;li&gt;Does not offer a &amp;quot;retry mechanism&amp;quot;, if a logic hook fails to deliver to a queue or contact an external system&lt;/li&gt;
&lt;li&gt;Synchronous in nature, requires a response from an external system&lt;/li&gt;
&lt;li&gt;Needs to handle dependencies manually (contact can only be created after account)&lt;/li&gt;
&lt;li&gt;Good to have a middleware/queue in front of Sugar to receive those event triggers to&amp;nbsp;reliably&amp;nbsp;manage peak loads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Realtime: Embed your app into Sugar&amp;nbsp;through &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/User_Interface/Dashlets/"&gt;Dashlets&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Simplest approach&lt;/li&gt;
&lt;li&gt;Often requires web user-based authentication&lt;/li&gt;
&lt;li&gt;All load/traffic goes directly to your system,&amp;nbsp;which makes your system the performance bottleneck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="rest"&gt;&lt;/a&gt;REST API Webservices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/7612.png" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;Accessing your data when you want is good. Accessing your data however you want is better. &lt;/span&gt;&lt;span&gt;When you decide to build an integration with Sugar, you&amp;rsquo;ll need an easy way to access and interact with the data stored in Sugar. The REST (&lt;/span&gt;&lt;span&gt;representational state transfer)&lt;/span&gt;&lt;span&gt;&amp;nbsp;API (application programming interface) is perfect for this.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sugar REST API Overview
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Fully RESTfull (GET, POST, PUT, DELETE)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;OAuth2 token based&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;All fields and modules are available through the API automatically&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Metadata API provides everything you need to know about your Sugar instance.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Topics
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/new-tutorial-intro-to-the-sugar-rest-api"&gt;Intro to the Sugar REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/how-sugar-rest-api-versioning-works"&gt;How Sugar REST API versioning works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/"&gt;RestAPI Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/sugarcrm-cookbook---the-school-of-rest---part-1"&gt;School of REST blog series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/"&gt;REST APIs Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Extending_Endpoints/"&gt;How to add your own custom endpoints to the REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/API_Exceptions/"&gt;API Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Best_Practices/"&gt;Best practices when integrating and migrating Sugar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="common"&gt;&lt;/a&gt;Common&amp;nbsp;APIs&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/3.png" /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;It is important to understand our most commonly used APIs and their functions within Sugar. Your integration might need data within Sugar&amp;#39;s module structure that could potentially change over time, so you can use Metadata for it as well as CRUD onto Sugar.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Metadata
&lt;ul&gt;
&lt;li&gt;Endpoint with current system&amp;#39;s structure&lt;/li&gt;
&lt;li&gt;Modules, fields, relationships, layouts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Use carefully, its payload can be MBs in size, cache as much as possible&lt;/li&gt;
&lt;li&gt;GET /metadata (use filters as much as possible)&lt;/li&gt;
&lt;li&gt;It does not retrieve labels for dropdowns, use language API to do so&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/3-tips-for-using-the-sugar-metadata-api"&gt;3 Tips for using the Sugar Metadata API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Language
&lt;ul&gt;
&lt;li&gt;Endpoint to retrieve labels&lt;/li&gt;
&lt;li&gt;Dropdown list values&lt;/li&gt;
&lt;li&gt;Any language-specific content&lt;/li&gt;
&lt;li&gt;GET /lang/&amp;lt;language_code&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CRUD (Create, Read, Update, Delete) records
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_GET"&gt;Read&lt;/a&gt;: &lt;code&gt;GET /&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/module_POST"&gt;Create&lt;/a&gt;: &lt;code&gt;POST /&amp;lt;module&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_PUT"&gt;Update&lt;/a&gt;: &lt;code&gt;PUT&amp;nbsp;&lt;span&gt;/&amp;lt;module&amp;gt;/:record&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_DELETE"&gt;Delete&lt;/a&gt;: &lt;code&gt;DELETE&amp;nbsp;/&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulefilter_POST"&gt;Filter&lt;/a&gt;: &lt;code&gt;POST /&amp;lt;module&amp;gt;/filter&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;You can use &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulefilter_GET"&gt;GET&lt;/a&gt; as well&lt;/li&gt;
&lt;li&gt;POST solves the issue when a query is too long and hits HTTP limits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecordlinklink_name_GET"&gt;Retrieve records related to another module&lt;/a&gt;:&amp;nbsp;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record/link/:link_name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecordlinklink_nameremote_id_POST"&gt;Creates a relationship to a pre-existing record:&lt;/a&gt;&lt;code&gt; POST /&amp;lt;module&amp;gt;/:record/link/:link_name/:remote_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="performance"&gt;&lt;/a&gt;Performance and Best Practices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/4.png" /&gt;&lt;/h1&gt;
&lt;div class="row"&gt;
&lt;div class="col-xs-12 col-md-9"&gt;
&lt;p&gt;As you deep dive into Sugar APIs,&amp;nbsp;you will see how easy it is to integrate to pull and push data from and to Sugar and your systems, however, you must consider performance so your integration doesn&amp;#39;t become a bottleneck between those systems.&lt;/p&gt;
&lt;p&gt;You should consider the following guidelines when implementing your integrations:&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar&amp;#39;s sync_key to link to remote IDs
&lt;ul&gt;
&lt;li&gt;Sugar provides in every module a sync_key field&lt;/li&gt;
&lt;li&gt;sync_key is a unique identifier for that module that links back to your external system&amp;#39;s generated key&lt;/li&gt;
&lt;li&gt;For example, account ID from ERP is AC0001, set sync_key (pass as a parameter in the POST) and sugar will create a record in account with sync_key=AC0001&lt;/li&gt;
&lt;li&gt;Next patch/update, sugar will check &amp;quot;where sync_key=&amp;#39;AC0001&amp;#39;&amp;quot; and update it (it is indexed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Integrate Upsert APIs
&lt;ul&gt;
&lt;li&gt;Sugar&amp;#39;s &amp;quot;update or insert&amp;quot; API based on sync_key&lt;/li&gt;
&lt;li&gt;Simplifies a common operation - if record exists, update it, otherwise create it (GET followed by a&amp;nbsp;PUT or POST)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_PATCH"&gt;Upsert by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_GET"&gt;Get by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_DELETE"&gt;Delete by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulerecord_idsync_key_field_namesync_key_field_value_PATCH"&gt;Set a sync on existing record (without sync_key)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_POST"&gt;Create relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_DELETE"&gt;Delete relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Bulk API
&lt;ul&gt;
&lt;li&gt;An endpoint that encapsulates multiple API calls into one single HTTP request&lt;/li&gt;
&lt;li&gt;Requests are executed synchronously (one after the other)&lt;/li&gt;
&lt;li&gt;Reducing network latency between calls&lt;/li&gt;
&lt;li&gt;Combined with Upsert provides the best performance&lt;/li&gt;
&lt;li&gt;Careful not to add too many requests to it&lt;/li&gt;
&lt;li&gt;Start small (5 to 10 requests) and increase until you reach its max capacity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Polling and filtering time-based with Filter API
&lt;ul&gt;
&lt;li&gt;Integration gateway (or your external system) asks Sugar every X minutes&lt;/li&gt;
&lt;li&gt;Request Filter API using &lt;code&gt;max_num&lt;/code&gt; (max number of records), offset and fields&lt;/li&gt;
&lt;li&gt;The response will provide the data as well as &lt;code&gt;next_offset&lt;/code&gt; (offset can be seen as pagination)&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;next_offset&lt;/code&gt; is -1, no more records to go through&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Initial Data Load into Sugar&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Use Bulk + Upsert to achieve data loads&lt;/li&gt;
&lt;li&gt;Millions&amp;nbsp;of records may take a little while to process, plan ahead (over the weekend)&lt;/li&gt;
&lt;li&gt;Use multi-thread processes to load (for example 20 threads sending 20 bulk upsert requests)&lt;/li&gt;
&lt;li&gt;Careful with&amp;nbsp;&lt;a href="https://support.sugarcrm.com/Resources/Sugar_Cloud_Policy_Guide/#Rate_Limits"&gt;Sugar Cloud rate limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&amp;#39;s always a good idea to let Sugar Support know you&amp;#39;re data loading, they will be considerate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Understanding PHP limitations&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;PHP is single-threaded with limited resources to process your request&lt;/li&gt;
&lt;li&gt;If you send too much data using bulk, you may run out of memory for that request&lt;/li&gt;
&lt;li&gt;Push to the limits but give some room for PHP to finish the request gracefully&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p id="mcetoc_1f5uvkqns0"&gt;&lt;span style="font-size:150%;"&gt;You&amp;#39;re up and running, but don&amp;#39;t stop now - this is just the beginning of your journey. &lt;/span&gt;&lt;/p&gt;
&lt;p id="mcetoc_1g9jl704d0"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Now it&amp;#39;s time for &lt;a href="/dev-club/dev-onboarding/w/documentation/676/customization-for-product-devs"&gt;Customizations&lt;/a&gt;.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Integrations for Product Devs</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs/revision/2</link><pubDate>Thu, 04 Aug 2022 05:30:05 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:e64c91c4-03e5-454f-bbd7-3beb25519ac3</guid><dc:creator>Alex Nassi</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs#comments</comments><description>Revision 2 posted to Dev Tutorials by Alex Nassi on 8/4/2022 5:30:05 AM&lt;br /&gt;
&lt;table style="margin-left:auto;margin-right:auto;width:100%;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#approach"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/1.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#rest"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/2.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#common"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/3.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;a href="#performance"&gt;&lt;img style="height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/4.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="approach"&gt;&lt;/a&gt;Integration Approaches&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/1.png" /&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;The Sugar platform is extremely powerful, flexible, and allows for easy integration. This flexibility means that determining the&amp;nbsp;best approach for your use case scenario is the key to success.&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Push/Pull from Sugar via REST API&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="text-decoration:underline;"&gt;Recommended&lt;/span&gt; approach&lt;/li&gt;
&lt;li&gt;Developers have full control over integration&lt;/li&gt;
&lt;li&gt;Integration can be stopped and systems will continue to work&lt;/li&gt;
&lt;li&gt;Retry mechanism: Resume integrations at any time (identify deltas through &amp;quot;last_update_time&amp;quot; flags)&lt;/li&gt;
&lt;li&gt;The time delay from/to Sugar is minimal&lt;/li&gt;
&lt;li&gt;Sugar REST API offers almost everything you need,&amp;nbsp;and can be further extended via customization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push to Sugar, Sugar pushes to an external queue in realtime&lt;span&gt;&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar Events to trigger through Logic Hooks&lt;/li&gt;
&lt;li&gt;Requires&amp;nbsp;Logic Hooks (code customization) to be created and deployed&lt;/li&gt;
&lt;li&gt;Does not offer a &amp;quot;retry mechanism&amp;quot;, if a logic hook fails to deliver to a queue or contact an external system&lt;/li&gt;
&lt;li&gt;Synchronous in nature, requires a response from an external system&lt;/li&gt;
&lt;li&gt;Needs to handle dependencies manually (contact can only be created after account)&lt;/li&gt;
&lt;li&gt;Good to have a middleware/queue in front of Sugar to receive those event triggers to&amp;nbsp;reliably&amp;nbsp;manage peak loads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Realtime: Embed your app into Sugar&amp;nbsp;through &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/User_Interface/Dashlets/"&gt;Dashlets&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Simplest approach&lt;/li&gt;
&lt;li&gt;Often requires web user-based authentication&lt;/li&gt;
&lt;li&gt;All load/traffic goes directly to your system,&amp;nbsp;which makes your system the performance bottleneck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="rest"&gt;&lt;/a&gt;REST API Webservices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/2.png" /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;Accessing your data when you want is good. Accessing your data however you want is better. &lt;/span&gt;&lt;span&gt;When you decide to build an integration with Sugar, you&amp;rsquo;ll need an easy way to access and interact with the data stored in Sugar. The REST (&lt;/span&gt;&lt;span&gt;representational state transfer)&lt;/span&gt;&lt;span&gt;&amp;nbsp;API (application programming interface) is perfect for this.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sugar REST API Overview
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Fully RESTfull (GET, POST, PUT, DELETE)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;OAuth2 token based&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;All fields and modules are available through the API automatically&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Metadata API provides everything you need to know about your Sugar instance.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Topics
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/new-tutorial-intro-to-the-sugar-rest-api"&gt;Intro to the Sugar REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/how-sugar-rest-api-versioning-works"&gt;How Sugar REST API versioning works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/"&gt;RestAPI Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/sugarcrm-cookbook---the-school-of-rest---part-1"&gt;School of REST blog series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/"&gt;REST APIs Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Extending_Endpoints/"&gt;How to add your own custom endpoints to the REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/API_Exceptions/"&gt;API Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Best_Practices/"&gt;Best practices when integrating and migrating Sugar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="common"&gt;&lt;/a&gt;Common&amp;nbsp;APIs&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/3.png" /&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;It is important to understand our most commonly used APIs and their functions within Sugar. Your integration might need data within Sugar&amp;#39;s module structure that could potentially change over time, so you can use Metadata for it as well as CRUD onto Sugar.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Metadata
&lt;ul&gt;
&lt;li&gt;Endpoint with current system&amp;#39;s structure&lt;/li&gt;
&lt;li&gt;Modules, fields, relationships, layouts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Use carefully, its payload can be MBs in size, cache as much as possible&lt;/li&gt;
&lt;li&gt;GET /metadata (use filters as much as possible)&lt;/li&gt;
&lt;li&gt;It does not retrieve labels for dropdowns, use language API to do so&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/3-tips-for-using-the-sugar-metadata-api"&gt;3 Tips for using the Sugar Metadata API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Language
&lt;ul&gt;
&lt;li&gt;Endpoint to retrieve labels&lt;/li&gt;
&lt;li&gt;Dropdown list values&lt;/li&gt;
&lt;li&gt;Any language-specific content&lt;/li&gt;
&lt;li&gt;GET /lang/&amp;lt;language_code&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CRUD (Create, Read, Update, Delete) records
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_GET"&gt;Read&lt;/a&gt;: &lt;code&gt;GET /&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/module_POST"&gt;Create&lt;/a&gt;: &lt;code&gt;POST /&amp;lt;module&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_PUT"&gt;Update&lt;/a&gt;: &lt;code&gt;PUT&amp;nbsp;&lt;span&gt;/&amp;lt;module&amp;gt;/:record&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_DELETE"&gt;Delete&lt;/a&gt;: &lt;code&gt;DELETE&amp;nbsp;/&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulefilter_POST"&gt;Filter&lt;/a&gt;: &lt;code&gt;POST /&amp;lt;module&amp;gt;/filter&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;You can use &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulefilter_GET"&gt;GET&lt;/a&gt; as well&lt;/li&gt;
&lt;li&gt;POST solves the issue when a query is too long and hits HTTP limits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecordlinklink_name_GET"&gt;Retrieve records related to another module&lt;/a&gt;:&amp;nbsp;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record/link/:link_name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecordlinklink_nameremote_id_POST"&gt;Creates a relationship to a pre-existing record:&lt;/a&gt;&lt;code&gt; POST /&amp;lt;module&amp;gt;/:record/link/:link_name/:remote_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="performance"&gt;&lt;/a&gt;Performance and Best Practices&lt;img class="align-right" style="float:right;height:auto;" alt=" " src="/resized-image/__size/2000x0/__key/communityserver-wikis-components-files/00-00-00-00-61/4.png" /&gt;&lt;/h1&gt;
&lt;div class="row"&gt;
&lt;div class="col-xs-12 col-md-9"&gt;
&lt;p&gt;As you deep dive into Sugar APIs,&amp;nbsp;you will see how easy it is to integrate to pull and push data from and to Sugar and your systems, however, you must consider performance so your integration doesn&amp;#39;t become a bottleneck between those systems.&lt;/p&gt;
&lt;p&gt;You should consider the following guidelines when implementing your integrations:&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar&amp;#39;s sync_key to link to remote IDs
&lt;ul&gt;
&lt;li&gt;Sugar provides in every module a sync_key field&lt;/li&gt;
&lt;li&gt;sync_key is a unique identifier for that module that links back to your external system&amp;#39;s generated key&lt;/li&gt;
&lt;li&gt;For example, account ID from ERP is AC0001, set sync_key (pass as a parameter in the POST) and sugar will create a record in account with sync_key=AC0001&lt;/li&gt;
&lt;li&gt;Next patch/update, sugar will check &amp;quot;where sync_key=&amp;#39;AC0001&amp;#39;&amp;quot; and update it (it is indexed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Integrate Upsert APIs
&lt;ul&gt;
&lt;li&gt;Sugar&amp;#39;s &amp;quot;update or insert&amp;quot; API based on sync_key&lt;/li&gt;
&lt;li&gt;Simplifies a common operation - if record exists, update it, otherwise create it (GET followed by a&amp;nbsp;PUT or POST)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_PATCH"&gt;Upsert by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_GET"&gt;Get by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_DELETE"&gt;Delete by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulerecord_idsync_key_field_namesync_key_field_value_PATCH"&gt;Set a sync on existing record (without sync_key)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_POST"&gt;Create relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_DELETE"&gt;Delete relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Bulk API
&lt;ul&gt;
&lt;li&gt;An endpoint that encapsulates multiple API calls into one single HTTP request&lt;/li&gt;
&lt;li&gt;Requests are executed synchronously (one after the other)&lt;/li&gt;
&lt;li&gt;Reducing network latency between calls&lt;/li&gt;
&lt;li&gt;Combined with Upsert provides the best performance&lt;/li&gt;
&lt;li&gt;Careful not to add too many requests to it&lt;/li&gt;
&lt;li&gt;Start small (5 to 10 requests) and increase until you reach its max capacity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Polling and filtering time-based with Filter API
&lt;ul&gt;
&lt;li&gt;Integration gateway (or your external system) asks Sugar every X minutes&lt;/li&gt;
&lt;li&gt;Request Filter API using &lt;code&gt;max_num&lt;/code&gt; (max number of records), offset and fields&lt;/li&gt;
&lt;li&gt;The response will provide the data as well as &lt;code&gt;next_offset&lt;/code&gt; (offset can be seen as pagination)&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;next_offset&lt;/code&gt; is -1, no more records to go through&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Initial Data Load into Sugar&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Use Bulk + Upsert to achieve data loads&lt;/li&gt;
&lt;li&gt;Millions&amp;nbsp;of records may take a little while to process, plan ahead (over the weekend)&lt;/li&gt;
&lt;li&gt;Use multi-thread processes to load (for example 20 threads sending 20 bulk upsert requests)&lt;/li&gt;
&lt;li&gt;Careful with&amp;nbsp;&lt;a href="https://support.sugarcrm.com/Resources/Sugar_Cloud_Policy_Guide/#Rate_Limits"&gt;Sugar Cloud rate limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&amp;#39;s always a good idea to let Sugar Support know you&amp;#39;re data loading, they will be considerate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Understanding PHP limitations&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;PHP is single-threaded with limited resources to process your request&lt;/li&gt;
&lt;li&gt;If you send too much data using bulk, you may run out of memory for that request&lt;/li&gt;
&lt;li&gt;Push to the limits but give some room for PHP to finish the request gracefully&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p id="mcetoc_1f5uvkqns0"&gt;&lt;span style="font-size:150%;"&gt;You&amp;#39;re up and running, but don&amp;#39;t stop now - this is just the beginning of your journey. &lt;/span&gt;&lt;/p&gt;
&lt;p id="mcetoc_1g9jl704d0"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Now it&amp;#39;s time for &lt;a href="/dev-club/dev-onboarding/w/documentation/676/customization-for-product-devs"&gt;Customizations&lt;/a&gt;.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Integrations for Product Devs</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs/revision/1</link><pubDate>Mon, 01 Aug 2022 19:52:01 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:e64c91c4-03e5-454f-bbd7-3beb25519ac3</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/708/integrations-for-product-devs#comments</comments><description>Revision 1 posted to Dev Tutorials by Rafael Fernandes on 8/1/2022 7:52:01 PM&lt;br /&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="#approach"&gt;&lt;img alt=" " src="/resized-image/__size/269x141/__key/communityserver-wikis-components-files/00-00-00-00-61/Screen-Shot-2022_2D00_07_2D00_14-at-11.42.25-AM.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="#rest"&gt;&lt;img alt=" " src="/resized-image/__size/270x141/__key/communityserver-wikis-components-files/00-00-00-00-61/Screen-Shot-2022_2D00_07_2D00_14-at-11.43.33-AM.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="#common"&gt;&lt;img alt=" " src="/resized-image/__size/270x141/__key/communityserver-wikis-components-files/00-00-00-00-61/Screen-Shot-2022_2D00_07_2D00_14-at-11.43.48-AM.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="#performance"&gt;&lt;img alt=" " src="/resized-image/__size/268x140/__key/communityserver-wikis-components-files/00-00-00-00-61/Screen-Shot-2022_2D00_07_2D00_14-at-11.44.04-AM.png" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="approach"&gt;&lt;/a&gt;Integration Approaches&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;The Sugar platform is extremely powerful, flexible, and allows for easy integration. This flexibility means that determining the&amp;nbsp;best approach for your use case scenario is the key to success.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img class="align-right" style="float:right;" alt=" " src="/resized-image/__size/269x141/__key/communityserver-wikis-components-files/00-00-00-00-61/Screen-Shot-2022_2D00_07_2D00_14-at-11.42.25-AM.png" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Push/Pull from Sugar via REST API&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="text-decoration:underline;"&gt;Recommended&lt;/span&gt; approach&lt;/li&gt;
&lt;li&gt;Developers have full control over integration&lt;/li&gt;
&lt;li&gt;Integration can be stopped and systems will continue to work&lt;/li&gt;
&lt;li&gt;Retry mechanism: Resume integrations at any time (identify deltas through &amp;quot;last_update_time&amp;quot; flags)&lt;/li&gt;
&lt;li&gt;The time delay from/to Sugar is minimal&lt;/li&gt;
&lt;li&gt;Sugar REST API offers almost everything you need,&amp;nbsp;and can be further extended via customization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push to Sugar, Sugar pushes to an external queue in realtime&lt;span&gt;&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar Events to trigger through Logic Hooks&lt;/li&gt;
&lt;li&gt;Requires&amp;nbsp;Logic Hooks (code customization) to be created and deployed&lt;/li&gt;
&lt;li&gt;Does not offer a &amp;quot;retry mechanism&amp;quot;, if a logic hook fails to deliver to a queue or contact an external system&lt;/li&gt;
&lt;li&gt;Synchronous in nature, requires a response from an external system&lt;/li&gt;
&lt;li&gt;Needs to handle dependencies manually (contact can only be created after account)&lt;/li&gt;
&lt;li&gt;Good to have a middleware/queue in front of Sugar to receive those event triggers to&amp;nbsp;reliably&amp;nbsp;manage peak loads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Realtime: Embed your app into Sugar&amp;nbsp;through &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/User_Interface/Dashlets/"&gt;Dashlets&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Simplest approach&lt;/li&gt;
&lt;li&gt;Often requires web user-based authentication&lt;/li&gt;
&lt;li&gt;All load/traffic goes directly to your system,&amp;nbsp;which makes your system the performance bottleneck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="rest"&gt;&lt;/a&gt;REST API Webservices&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;Accessing your data when you want is good. Accessing your data however you want is better. &lt;/span&gt;&lt;span&gt;When you decide to build an integration with Sugar, you&amp;rsquo;ll need an easy way to access and interact with the data stored in Sugar. The REST (&lt;/span&gt;&lt;span&gt;representational state transfer)&lt;/span&gt;&lt;span&gt;&amp;nbsp;API (application programming interface) is perfect for this.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sugar REST API Overview
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Fully RESTfull (GET, POST, PUT, DELETE)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;OAuth2 token based&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;All fields and modules are available through the API automatically&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Metadata API provides everything you need to know about your Sugar instance.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;img class="align-right" style="float:right;" alt=" " src="/resized-image/__size/270x141/__key/communityserver-wikis-components-files/00-00-00-00-61/Screen-Shot-2022_2D00_07_2D00_14-at-11.43.33-AM.png" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Topics
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/new-tutorial-intro-to-the-sugar-rest-api"&gt;Intro to the Sugar REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/how-sugar-rest-api-versioning-works"&gt;How Sugar REST API versioning works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/"&gt;RestAPI Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/sugarcrm-cookbook---the-school-of-rest---part-1"&gt;School of REST blog series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/"&gt;REST APIs Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Extending_Endpoints/"&gt;How to add your own custom endpoints to the REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/API_Exceptions/"&gt;API Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Best_Practices/"&gt;Best practices when integrating and migrating Sugar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1f4f3gg1d0"&gt;&lt;span&gt;&lt;a id="common"&gt;&lt;/a&gt;Common&amp;nbsp;APIs&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span&gt;It is important to understand our most commonly used APIs and their functions within Sugar. Your integration might need data within Sugar&amp;#39;s module structure that could potentially change over time, so you can use Metadata for it as well as CRUD onto Sugar.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class="align-right" style="float:right;" alt=" " src="/resized-image/__size/270x141/__key/communityserver-wikis-components-files/00-00-00-00-61/Screen-Shot-2022_2D00_07_2D00_14-at-11.43.48-AM.png" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Metadata
&lt;ul&gt;
&lt;li&gt;Endpoint with current system&amp;#39;s structure&lt;/li&gt;
&lt;li&gt;Modules, fields, relationships, layouts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Use carefully, its payload can be MBs in size, cache as much as possible&lt;/li&gt;
&lt;li&gt;GET /metadata (use filters as much as possible)&lt;/li&gt;
&lt;li&gt;It does not retrieve labels for dropdowns, use language API to do so&lt;/li&gt;
&lt;li&gt;&lt;a href="/dev-club/b/dev-blog/posts/3-tips-for-using-the-sugar-metadata-api"&gt;3 Tips for using the Sugar Metadata API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Language
&lt;ul&gt;
&lt;li&gt;Endpoint to retrieve labels&lt;/li&gt;
&lt;li&gt;Dropdown list values&lt;/li&gt;
&lt;li&gt;Any language-specific content&lt;/li&gt;
&lt;li&gt;GET /lang/&amp;lt;language_code&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CRUD (Create, Read, Update, Delete) records
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_GET"&gt;Read&lt;/a&gt;: &lt;code&gt;GET /&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/module_POST"&gt;Create&lt;/a&gt;: &lt;code&gt;POST /&amp;lt;module&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_PUT"&gt;Update&lt;/a&gt;: &lt;code&gt;PUT&amp;nbsp;&lt;span&gt;/&amp;lt;module&amp;gt;/:record&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecord_DELETE"&gt;Delete&lt;/a&gt;: &lt;code&gt;DELETE&amp;nbsp;/&amp;lt;module&amp;gt;/:record&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulefilter_POST"&gt;Filter&lt;/a&gt;: &lt;code&gt;POST /&amp;lt;module&amp;gt;/filter&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;You can use &lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulefilter_GET"&gt;GET&lt;/a&gt; as well&lt;/li&gt;
&lt;li&gt;POST solves the issue when a query is too long and hits HTTP limits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecordlinklink_name_GET"&gt;Retrieve records related to another module&lt;/a&gt;:&amp;nbsp;&lt;code&gt;GET /&amp;lt;module&amp;gt;/:record/link/:link_name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/Endpoints/modulerecordlinklink_nameremote_id_POST"&gt;Creates a relationship to a pre-existing record:&lt;/a&gt;&lt;code&gt; POST /&amp;lt;module&amp;gt;/:record/link/:link_name/:remote_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1 id="mcetoc_1g6ls8l4i0"&gt;&lt;a id="performance"&gt;&lt;/a&gt;Performance and Best Practices&lt;/h1&gt;
&lt;div class="row"&gt;
&lt;div class="col-xs-12 col-md-9"&gt;
&lt;p&gt;As you deep dive into Sugar APIs,&amp;nbsp;you will see how easy it is to integrate to pull and push data from and to Sugar and your systems, however, you must consider performance so your integration doesn&amp;#39;t become a bottleneck between those systems.&lt;/p&gt;
&lt;p&gt;You should consider the following guidelines when implementing your integrations:&lt;/p&gt;
&lt;p&gt;&lt;img class="align-right" style="float:right;" alt=" " src="/resized-image/__size/268x140/__key/communityserver-wikis-components-files/00-00-00-00-61/Screen-Shot-2022_2D00_07_2D00_14-at-11.44.04-AM.png" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Use Sugar&amp;#39;s sync_key to link to remote IDs
&lt;ul&gt;
&lt;li&gt;Sugar provides in every module a sync_key field&lt;/li&gt;
&lt;li&gt;sync_key is a unique identifier for that module that links back to your external system&amp;#39;s generated key&lt;/li&gt;
&lt;li&gt;For example, account ID from ERP is AC0001, set sync_key (pass as a parameter in the POST) and sugar will create a record in account with sync_key=AC0001&lt;/li&gt;
&lt;li&gt;Next patch/update, sugar will check &amp;quot;where sync_key=&amp;#39;AC0001&amp;#39;&amp;quot; and update it (it is indexed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Integrate Upsert APIs
&lt;ul&gt;
&lt;li&gt;Sugar&amp;#39;s &amp;quot;update or insert&amp;quot; API based on sync_key&lt;/li&gt;
&lt;li&gt;Simplifies a common operation - if record exists, update it, otherwise create it (GET followed by a&amp;nbsp;PUT or POST)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_PATCH"&gt;Upsert by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_GET"&gt;Get by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulesync_key_field_namesync_key_field_value_DELETE"&gt;Delete by sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulerecord_idsync_key_field_namesync_key_field_value_PATCH"&gt;Set a sync on existing record (without sync_key)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_POST"&gt;Create relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.sugarcrm.com/SmartLinks/Developer_Guide/Integration/Web_Services/REST_API/Endpoints/Integratemodulelhs_sync_key_field_namelhs_sync_key_field_valuelinklink_namerhs_sync_key_field_namerhs_sync_key_field_value_DELETE"&gt;Delete relationship based on sync_key&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Sugar Bulk API
&lt;ul&gt;
&lt;li&gt;An endpoint that encapsulates multiple API calls into one single HTTP request&lt;/li&gt;
&lt;li&gt;Requests are executed synchronously (one after the other)&lt;/li&gt;
&lt;li&gt;Reducing network latency between calls&lt;/li&gt;
&lt;li&gt;Combined with Upsert provides the best performance&lt;/li&gt;
&lt;li&gt;Careful not to add too many requests to it&lt;/li&gt;
&lt;li&gt;Start small (5 to 10 requests) and increase until you reach its max capacity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Polling and filtering time-based with Filter API
&lt;ul&gt;
&lt;li&gt;Integration gateway (or your external system) asks Sugar every X minutes&lt;/li&gt;
&lt;li&gt;Request Filter API using &lt;code&gt;max_num&lt;/code&gt; (max number of records), offset and fields&lt;/li&gt;
&lt;li&gt;The response will provide the data as well as &lt;code&gt;next_offset&lt;/code&gt; (offset can be seen as pagination)&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;next_offset&lt;/code&gt; is -1, no more records to go through&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Initial Data Load into Sugar&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Use Bulk + Upsert to achieve data loads&lt;/li&gt;
&lt;li&gt;Millions&amp;nbsp;of records may take a little while to process, plan ahead (over the weekend)&lt;/li&gt;
&lt;li&gt;Use multi-thread processes to load (for example 20 threads sending 20 bulk upsert requests)&lt;/li&gt;
&lt;li&gt;Careful with&amp;nbsp;&lt;a href="https://support.sugarcrm.com/Resources/Sugar_Cloud_Policy_Guide/#Rate_Limits"&gt;Sugar Cloud rate limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&amp;#39;s always a good idea to let Sugar Support know you&amp;#39;re data loading, they will be considerate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Understanding PHP limitations&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;PHP is single-threaded with limited resources to process your request&lt;/li&gt;
&lt;li&gt;If you send too much data using bulk, you may run out of memory for that request&lt;/li&gt;
&lt;li&gt;Push to the limits but give some room for PHP to finish the request gracefully&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h3 id="mcetoc_1f5uvkqns0"&gt;&lt;span style="font-size:inherit;"&gt;You&amp;#39;re up and running, but don&amp;#39;t stop now - this is just the beginning of your journey. Now it&amp;#39;s time to &lt;a href="/dev-club/dev-onboarding/w/documentation/686/customization-for-devs"&gt;Customizations&lt;/a&gt;.&lt;/span&gt;&lt;/h3&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item></channel></rss>