title: CRM WEB API Batch
body: <p>I am fairly new to CRM Web API and coding in general but I did want to try my hand at this regardless.</p>
  <p>I was trying to implement a custom &quot;convert Contract to Invoice&quot; functionality by first creating an Invoice with the data from a contract and secondly create an InvoiceDetail from ContractDetail/lines, which kind of works via httprequests, though very quickly I have noticed that requesting and posting data in such a way is very limited. I've read that its possible to work with more data by utilizing batches, however I am not really sure how to convert my code to batch appropriately.</p>
  <p>I'd really appreciate any kind of help in that regard!</p>
  <pre><code>function retrieveProducts(data, newInvoiceID) {
      var data = data;
      var ID = newInvoiceID;
  
      for (var i = 0; i &lt; data.length; i++) {
          var existingProduct = data[i];
  
          var lineitem = {};
          lineitem[&quot;productid@odata.bind&quot;] = &quot;/products(&quot; + existingProduct._productid_value + &quot;)&quot;;
          lineitem[&quot;uomid@odata.bind&quot;] = &quot;/uoms(&quot; + existingProduct._uomid_value + &quot;)&quot;;
          lineitem[&quot;new_contractactiveon&quot;] = existingProduct.activeon;
          lineitem[&quot;new_contractexpireson&quot;] = existingProduct.expireson;
          lineitem.quantity = existingProduct.initialquantity;
          lineitem[&quot;invoiceid@odata.bind&quot;] = &quot;/invoices(&quot;+ ID +&quot;)&quot;;
          createRecords(lineitem);
      }
  }
  
  </code></pre>
  <pre><code>    function createRecords(data) {
      var req = new XMLHttpRequest();
  req.open(&quot;POST&quot;, Xrm.Page.context.getClientUrl() + &quot;/api/data/v8.2/invoicedetails&quot;, false);
  req.setRequestHeader(&quot;OData-MaxVersion&quot;, &quot;4.0&quot;);
  req.setRequestHeader(&quot;OData-Version&quot;, &quot;4.0&quot;);
  req.setRequestHeader(&quot;Accept&quot;, &quot;application/json&quot;);
  req.setRequestHeader(&quot;Content-Type&quot;, &quot;application/json; charset=utf-8&quot;);
  req.onreadystatechange = function() {
      if (this.readyState === 4) {
          req.onreadystatechange = null;
          if (this.status === 204) {
              var uri = this.getResponseHeader(&quot;OData-EntityId&quot;);
              var regExp = /\(([^)]+)\)/;
              var matches = regExp.exec(uri);
              var newEntityId = matches[1];
          } else {
              Xrm.Utility.alertDialog(this.statusText);
          }
      }
  };
  req.send(JSON.stringify(data));
  }
  </code></pre>
  <p>EDIT: Here the full code</p>
  <pre><code>function start() {
      var ID = parent.Xrm.Page.data.entity.getId().substring(1, 37);
      var fetchxml = `
  
  &lt;fetch distinct=&quot;false&quot; mapping=&quot;logical&quot; output-format=&quot;xml-platform&quot; version=&quot;1.0&quot;&gt;
  &lt;entity name=&quot;contractdetail&quot;&gt;
  &lt;attribute name=&quot;title&quot;/&gt;
  &lt;attribute name=&quot;productid&quot;/&gt;
  &lt;attribute name=&quot;allotmentsremaining&quot;/&gt;
  &lt;attribute name=&quot;contractdetailid&quot;/&gt;
  &lt;attribute name=&quot;net&quot;/&gt;
  &lt;attribute name=&quot;activeon&quot;/&gt;
  &lt;attribute name=&quot;serviceaddress&quot;/&gt;
  &lt;attribute name=&quot;initialquantity&quot;/&gt;
  &lt;attribute name=&quot;customerid&quot;/&gt;
  &lt;attribute name=&quot;expireson&quot;/&gt;
  &lt;attribute name=&quot;uomid&quot;/&gt;
  &lt;attribute name=&quot;new_ortfirma&quot;/&gt;
  &lt;order descending=&quot;false&quot; attribute=&quot;title&quot;/&gt;
  &lt;link-entity name=&quot;contract&quot; alias=&quot;ab&quot; to=&quot;contractid&quot; from=&quot;contractid&quot;&gt;
  &lt;filter type=&quot;and&quot;&gt;
  &lt;condition attribute=&quot;contractid&quot; value=&quot;{` + ID + `}&quot; uitype=&quot;contract&quot; operator=&quot;eq&quot;/&gt;
  &lt;/filter&gt;
  &lt;/link-entity&gt;
  &lt;/entity&gt;
  &lt;/fetch&gt;`;
  
      var encodedFetchXML = encodeURIComponent(fetchxml);
      var queryPath = &quot;/api/data/v8.2/contractdetails?fetchXml=&quot; + encodedFetchXML;
      var requestPath = parent.Xrm.Page.context.getClientUrl() + queryPath;
  
      var req = new XMLHttpRequest();
      req.open(&quot;GET&quot;, requestPath, true);
      req.setRequestHeader(&quot;Accept&quot;, &quot;application/json&quot;);
      req.setRequestHeader(&quot;Content-Type&quot;, &quot;application/json; charset=utf-8&quot;);
      req.setRequestHeader(&quot;Prefer&quot;, &quot;odata.include-annotations=\&quot;*\&quot;&quot;);
      req.onreadystatechange = function ()
  
      {
  
          if (this.readyState === 4)
  
          {
  
              this.onreadystatechange = null;
              if (this.status === 200)
  
              {
                  var returned = JSON.parse(this.responseText);
                  var results = returned.value;
                  
                  getContractInfo(results);
              } else
  
              {
  
                  alert(this.statusText);
  
              }
  
          }
  
      };
   
      req.send();
      window.alert(&quot;Invoice created.&quot;);
      setStatus(ID);
  }
  
  function retrieveProducts(data, newInvoiceID) {
      var data = data;
      var ID = newInvoiceID;
  
      for (var i = 0; i &lt; data.length; i++) {
          var existingProduct = data[i];
  
          var lineitem = {};
          lineitem[&quot;productid@odata.bind&quot;] = &quot;/products(&quot; + existingProduct._productid_value + &quot;)&quot;;
          lineitem[&quot;uomid@odata.bind&quot;] = &quot;/uoms(&quot; + existingProduct._uomid_value + &quot;)&quot;;
          lineitem[&quot;new_contractactiveon&quot;] = existingProduct.activeon;
          lineitem[&quot;new_contractexpireson&quot;] = existingProduct.expireson;
          lineitem[&quot;new_ortfirma@odata.bind&quot;] = &quot;/accounts(&quot; + existingProduct._new_ortfirma_value + &quot;)&quot;;
          lineitem.quantity = existingProduct.initialquantity;
          lineitem[&quot;invoiceid@odata.bind&quot;] = &quot;/invoices(&quot;+ ID +&quot;)&quot;;
          createRecords(lineitem);
      }
  }
  
  function setStatus(ID) {
  var entity = {};
  entity.statecode = 1;
  entity.statuscode = 2;
  
  var req = new XMLHttpRequest();
  req.open(&quot;PATCH&quot;, parent.Xrm.Page.context.getClientUrl() + &quot;/api/data/v8.2/contracts(ED9C4959-A951-EB11-BC99-00155DB20709)&quot;, true);
  req.setRequestHeader(&quot;OData-MaxVersion&quot;, &quot;4.0&quot;);
  req.setRequestHeader(&quot;OData-Version&quot;, &quot;4.0&quot;);
  req.setRequestHeader(&quot;Accept&quot;, &quot;application/json&quot;);
  req.setRequestHeader(&quot;Content-Type&quot;, &quot;application/json; charset=utf-8&quot;);
  req.onreadystatechange = function() {
      if (this.readyState === 4) {
          req.onreadystatechange = null;
          if (this.status === 204) {
              //Success - No Return Data - Do Something
          } else {
              parent.Xrm.Utility.alertDialog(this.statusText);
          }
      }
  };
  req.send(JSON.stringify(entity));
  }
  
  function createRecords(data) {
      var req = new XMLHttpRequest();
  req.open(&quot;POST&quot;, parent.Xrm.Page.context.getClientUrl() + &quot;/api/data/v8.2/invoicedetails&quot;, false);
  req.setRequestHeader(&quot;OData-MaxVersion&quot;, &quot;4.0&quot;);
  req.setRequestHeader(&quot;OData-Version&quot;, &quot;4.0&quot;);
  req.setRequestHeader(&quot;Accept&quot;, &quot;application/json&quot;);
  req.setRequestHeader(&quot;Content-Type&quot;, &quot;application/json; charset=utf-8&quot;);
  req.onreadystatechange = function() {
      if (this.readyState === 4) {
          req.onreadystatechange = null;
          if (this.status === 204) {
              var uri = this.getResponseHeader(&quot;OData-EntityId&quot;);
              var regExp = /\(([^)]+)\)/;
              var matches = regExp.exec(uri);
              var newEntityId = matches[1];
          } else {
              parent.Xrm.Utility.alertDialog(this.statusText);
          }
      }
  };
  req.send(JSON.stringify(data));
  }
  
  
  //info from contact that is going to be used in the invoice
  function getContractInfo(data) {
      var ID = parent.Xrm.Page.data.entity.getId().substring(1, 37);
  
      var req = new XMLHttpRequest();
      req.open(&quot;GET&quot;, parent.Xrm.Page.context.getClientUrl() + &quot;/api/data/v8.2/contracts(&quot; + ID + &quot;)?$select=activeon,_customerid_value,expireson,_serviceaddress_value,title&amp;$expand=contract_line_items($select=activeon,expireson,initialquantity,price,title)&quot;, true);
      req.setRequestHeader(&quot;OData-MaxVersion&quot;, &quot;4.0&quot;);
      req.setRequestHeader(&quot;OData-Version&quot;, &quot;4.0&quot;);
      req.setRequestHeader(&quot;Accept&quot;, &quot;application/json&quot;);
      req.setRequestHeader(&quot;Content-Type&quot;, &quot;application/json; charset=utf-8&quot;);
      req.setRequestHeader(&quot;Prefer&quot;, &quot;odata.include-annotations=\&quot;*\&quot;&quot;);
      req.onreadystatechange = function () {
          if (this.readyState === 4) {
              req.onreadystatechange = null;
              if (this.status === 200) {
                  var result = JSON.parse(this.response);
                  var activeon = result[&quot;activeon&quot;];
                  var _customerid_value = result[&quot;_customerid_value&quot;];
                  var expireson = result[&quot;expireson&quot;];
                  var title = result[&quot;title&quot;];
  
                  createInvoice(_customerid_value, title, data, activeon, expireson);
              } else {
                  parent.Xrm.Utility.alertDialog(this.statusText);
              }
          }
      };
      req.send();
  }
  //create the invoice
  function createInvoice(customer, title, data, activeon, expireson) {
  
      var entity = {};
      entity[&quot;customerid_account@odata.bind&quot;] = &quot;/accounts(&quot; + customer + &quot;)&quot;;
      entity[&quot;pricelevelid@odata.bind&quot;] = &quot;/pricelevels(be2084c3-1e50-eb11-bc99-00155db20709)&quot;;
      entity.name = title;
      entity[&quot;transactioncurrencyid@odata.bind&quot;] = &quot;/transactioncurrencies(59f3fa86-385a-ea11-bc6a-00155db20709)&quot;;
      entity.new_contractactiveon = activeon;
      entity.new_contractexpireson = expireson;
  
      var req = new XMLHttpRequest();
      req.open(&quot;POST&quot;, parent.Xrm.Page.context.getClientUrl() + &quot;/api/data/v8.2/invoices&quot;, true);
      req.setRequestHeader(&quot;OData-MaxVersion&quot;, &quot;4.0&quot;);
      req.setRequestHeader(&quot;OData-Version&quot;, &quot;4.0&quot;);
      req.setRequestHeader(&quot;Accept&quot;, &quot;application/json&quot;);
      req.setRequestHeader(&quot;Content-Type&quot;, &quot;application/json; charset=utf-8&quot;);
      req.onreadystatechange = function () {
          if (this.readyState === 4) {
              req.onreadystatechange = null;
              if (this.status === 204) {
                  var uri = this.getResponseHeader(&quot;OData-EntityId&quot;);
                  var regExp = /\(([^)]+)\)/;
                  var matches = regExp.exec(uri);
                  var newEntityId = matches[1];
                  var ID = this.getResponseHeader(&quot;OData-EntityId&quot;).substring(67,103); 
                  retrieveProducts(data, ID);
  
                  
                  
              } else {
                  parent.Xrm.Utility.alertDialog(this.statusText);
              }
          }
      };
      req.send(JSON.stringify(entity));
  
  }
  </code></pre>