Composite API - An Overview

The composite API allows you to combine up to five API calls in a single request consuming just one credit per composite call. This API reduces the round-trip time and allows you to execute the APIs in a single database transaction, if needed.
By single database transaction, we mean that your request can have multiple sub-requests (individual APIs), and the execution can happen in a sequence. You will get a response when all the sub-requests are executed successfully, or after the entire composite request is rolled-back(all changes reverted) owing to the failure of a single sub-request.

What is Round-trip time (RTT) and how does this API reduce it?
The time taken for a client request to reach the server and render a response back in the client is called the Round-trip time.
Since you club all the requests in a composite API, round-trip time is saved. Should one or more of the sub-requests fail, you can choose to rollback (revert all the changes) the entire transaction.

The keys "rollback_on_fail" and "concurrent_execution"

  • rollback_on_fail: This boolean key represents whether you want to rollback the composite request when one or more sub-requests fail.

  • concurrent_execution: This boolean key represents whether you want to process all the independent sub-requests in parallel.

Let us discuss the two scenarios in which this API is at its best.

  1. Sub-requests are not executed under the same transaction
    • 1.a. Independent APIs (requests are served concurrently, rollback_on_fail:false, concurrent_exec:true))
      Consider that you want to fetch the metadata of the Leads module, its layouts, fields, and custom views. Instead of making four individual API calls and losing four credits, you can use the composite API for just one credit. On our server side, we will process the API calls in parallel. Here is the sample request.

      {
          "__composite_requests": [
              {
                  "uri": "/crm/v3/settings/modules/Leads",
                  "method": "GET"
              },
              {
                  "uri": "/crm/v3/settings/fields",
                  "method": "GET",
                  "params": {
                      "module": "Leads"
                  }
              },
              {
                  "uri": "/crm/v3/settings/layouts",
                  "method": "GET",
                  "params": {
                      "module": "Leads"
                  }
              },
              {
                  "uri": "/crm/v3/settings/custom_views",
                  "method": "GET",
                  "params": {
                      "module": "Leads"
                  }
              }
          ]
      }
      
    • 1.b. With dependent sub-requests (requests are served sequentially, rollback_on_fail:false, concurrent_exec:true)
      Consider a use case where you update a contact's Lead Source to Employee Referral in a sub-request. In sub-request 2, you insert a lead that triggers a workflow when the related contact's lead source is employee referral.
      In parallel execution, we cannot guarantee that sub-request 1 is served first followed by sub-request 2. So, the workflow might not be updated in sub-request 2 as the criteria will not be met before serving sub-request 1. In this case, sequential execution is the way to go. Here is how the request looks:

      {
          "concurrent_execution": false,
          "__composite_requests": [
              {
                  "uri": "/crm/v3/Contacts",
                  "method": "PUT",
                  "body": {
                      "data": [
                          {
                              "Lead_Source": "Employee_Referral",
                              "id": 111111000000106240
                          }
                      ]
                  }
              },
              {
                  "uri": "/crm/v3/Leads",
                  "method": "POST",
                  "body": {
                      "data": [
                          {
                              "Last_Name": "Boyle"
                          }
                      ]
                  }
              }
          ]
      }
      
  2. Sub Requests are executed under the same transaction (rollback_on_fail:true, concurrent_exec:false)
    This flow is useful when your custom business logic is complex and demands multiple operations in a single transaction. Consider an example where you want to close a deal, create a quote for that deal, and add a tag to that quote.
    This composite API call consumes one credit on successful execution and also when a rollback is performed.
    The input would look like the following.

    {
    "rollback_on_fail":true,
        "__composite_requests":[
            {
                 "uri":"/crm/v3/Deals",
                 "method":"PUT",
                 "body": {
                    "data":
                    [
                        {
                            "Stage":"Closed Won",
                            "Closing_Date":"2022-04-30",
                            "id":111111000000056144
                        }
                    ]
                 },
                 "sub_request_id":"1"
            },
             {
                 "uri":"/crm/v3/Quotes",
                 "sub_request_id":"2",
                 "method":"POST",
                 "body":{
                    "data":[
                        {
                            "Product_Details":[
                                {
                                    "product":{
                                        "id":"111111000000106008"
                                    },
                                    "quantity":1
                                 }
                            ],
                            "Subject":"Quotes1",
                            "Deal_Name":"@{1:$.data[0].details.id}"
                        }
                    ]
                }
            },
            {
                 "uri":"/crm/v3/Quotes/@{2:$.data[0].details.id}/actions/add_tags",
                 "method":"POST",
                 "params":{
                     "tag_names":"T1"
                 }
            }
        ]}}