Table of Contents
Last updated: 2024-06-26

Batch API


The batch API route allows for a REST client to make multiple REST API operations in one single HTTP request. Typically this functionality would be used in a "multi edit"-scenario but this feature can be used for multiple use cases. It is however important to consider the implications of making too large requests (more on this later).

Example usages:

  • Reading multiple SoftType instances in one call. E.g. loading SoftType instances according to a schema based on the result from one query page.
  • Creating/Updating multiple SoftType instances in one call.

All create and update operations within one batch request will be committed in one change set. If one of the operations fail all of the operations will be aborted and rolled back.

Advantages:

  • Cutting out the HTTP request lead times of single requests in sequence.
  • Allowing for edits and creates using one commit.

Restrictions


While it can be difficult to estimate the limitations of the batch API there are some guidelines to follow. The reason for this being that because of the configuration possibilities of ShareAspace the request payload size is very dependent on the configuration.

Guidelines:

  • A request should not take more than 30 seconds. If your requests takes longer - consider using smaller batches.
  • ~100 operations per batch can be a good mark as long as the first bullet in this list is fulfilled.

There is no hard limit within the REST API - however the default request timeout of the server/client connection can make it seem like the request did not finish. A request that takes longer than the default request time will however finish executing (without a response being returned).

Warning

The risk of running many large requests (more than 30 seconds), especially running many larger requests in parallel, is that the response times of other requests might be affected in a negative way (in terms of response times). Increasing the request timeouts is not a good solution.

Tip

If you have a business scenario demanding larger data reads and/or single change set commits of multiple create/updates that cannot be handled within the restrictions of the batch API. Consider using the import/export functionality of ShareAspace instead.

Supported routes

With the batch API it is not possible to use all the routes in the API. The supported routes are the routes found in the areas:

  • SoftType
    • GET
    • POST
    • PUT
    • PATCH
  • Maturity Action
    • PUT - Promote
    • PUT - Demote
  • Lock objects

Use


Request

The batch call is a POST of an array of individual operations to the route:

POST /api/space/{spaceId}/batch

Each operation in the array should have:

Property Description
method Required The HTTP verb of the request within the batch. GET, POST, PUT, PATCH, DELETE.
href Required The full API URI for the request to be performed. E.g. https://my.machine1.net/api/space/myspace/softtype/MySoftType/defaultIn.
body Dependent The payload of the request. This depends on the API routs and HTTP verb. Controlled by the definition of the API.
headers Dependent The headers that go with the request. Depends on the API route and HTTP verb. Note that the Authorizaiton and SAs.InformationFilter headers does not have to be duplicated here. The batch request will use the Authorizaiton and SAs.InformationFilter headers from the batch request itself. The Etag and SAs-UOIVersion headers can be applicable here.

Request Payload example

[
  {
    "method": "POST",
    "href": "https://vm15/api/space/ic/softtype/DesignPart/defaultIn",
    "body": ...
  },
  {
    "method": "POST",
    "href": "https://vm15/api/space/ic/softtype/DesignPart/defaultIn",
    "body": ...
  }
]
Note

It is not possible to create a relation between two SoftType instances that are created in the same batch call.

Method

The method field has the same meaning as the corresponding HTTP verb of the same name. More specifically how Nova uses them is:

  • GET : For retrieving objects.
  • POST : For creating objects.
  • PUT : For editing objects where any field not included in the body is removed from the object. In other words, the PUT method replaces all current fields of the target object with the request payload
  • PATCH : For editing objects where only the fields included in the body are edited and any other fields not mentioned in the body are left as they were before the edit. In other words, the PATCH method is used to apply partial modifications to an object.
  • DELETE. For deleting objects.

Response

The status code of the response can be one of the following:

Code Description
200 OK, all operations passed with success.
500 Error, at least one operation failed.

The individual status codes per operation can be viewed in the response message. The response message is an array of the result for each operation, in the message the following data can be found:

Property Description
statusCode The status code for the operation e.g. 201 or 204. Read more about the codes here.
body An object with the properties href and version.
href Replaces what would normally be returned in the Location response header. I.e. the URI to the created/updated resource. E.g. https://vm15/api/space/ic/softtype/DesignPart/0a000000000000001201060000000400
version Replaces what would normally be returned in the SAs-UOIVersion response header. I.e. the system version of the object.

Response Payload example

[
  {
    "statusCode": 201,
    "body": {
      "href": "https://vm15/api/space/ic/softtype/DesignPart/0900000...000400",
      "version": 1
    }
  },
  {
    "statusCode": 201,
    "body": {
      "href": "https://vm15/api/space/ic/softtype/DesignPart/0900000...000401",
      "version": 1
    }
  }
]

Code Example In C-Sharp


Caution

Sample code provided in here is for demonstration and educational purposes only which provides customers with programming information regarding the products and is not intended for use in a production environment. All production code should always follow development best practices. All sample code here is supplied "AS IS" without any warranties or support.

The provided C# code uses HttpClient to make the REST calls.

Warning

A common mistake when using HttpClient is to use multiple instances of the HttpClient. You should reuse the same instance within an application.

Authentication

First we need to authenticate and retrieve an access token. This is done using the ResourceOwner flow that has to be configured in the collection bootstrap.

First we create a helper authentication header class:

BasicAuthenticationHeaderValue

using System;
using System.Net.Http.Headers;
using System.Text;

namespace Demo.BatchApi
{
    public class BasicAuthenticationHeaderValue : AuthenticationHeaderValue
    {
        public BasicAuthenticationHeaderValue(string clientId, string clientSecret)
            : base("Basic", EncodeCredential(clientId, clientSecret))
        {
        }

        private static string EncodeCredential(string clientId, string clientSecret)
        {
            return Convert.ToBase64String(
                Encoding.UTF8.GetBytes(string.Format("{0}:{1}", new object[2]
                {
                    clientId,
                    clientSecret
                })));
        }
    }
}

And then the actual authentication using the header from above, the returned token will be used in the examples.

Authentication

using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Net.Http;

namespace Demo.BatchApi
{
    public static partial class Program
    {
        public static JObject Authenticate(string baseAddress, string userName, string password, string clientId, string clientSecret)
        {
            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Authorization = new BasicAuthenticationHeaderValue(clientId, clientSecret);

            var form = new Dictionary<string, string>
            {
                {"grant_type", "password"},
                {"username", userName},
                {"password", password},
                {"scope", "All" }
            };

            HttpContent content = new FormUrlEncodedContent(form);
            string requestUri = $"{baseAddress}/AuthorizationServer/sasweb/oauth/token";
            HttpResponseMessage response = client.PostAsync(requestUri, content).Result;
            response.EnsureSuccessStatusCode();
            string responseContent = response.Content.ReadAsStringAsync().Result;
            JObject token = JObject.Parse(responseContent);
            client.Dispose();
            return token;
        }
    }
}

Batch Commit

The batch call is just a post call to a URI with a body containing json where the response is a body containing json, this batch commit call is reused in the examples.

Batch Commit

using Newtonsoft.Json.Linq;
using System.Net.Http;
using System.Net.Http.Headers;

namespace Demo.BatchApi
{
    public static partial class Program
    {
        public static JArray BatchCommit(string accessToken, string baseAddress, string spaceId, JArray operations)
        {
            string requestUri = $"{baseAddress}/api/space/{spaceId}/batch";
            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            var content = new StringContent(operations.ToString());
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            HttpResponseMessage response = client.PostAsync(requestUri, content).Result;
            string responseValue = response.Content.ReadAsStringAsync().Result;
            JArray result = JArray.Parse(responseValue);
            response.EnsureSuccessStatusCode();
            client.Dispose();
            return result;
        }
    }
}

Batch SoftType Create

Here is an example of how to create two DesignParts from the InControl space template.

Batch Create Code

using Newtonsoft.Json.Linq;
using System;

namespace Demo.BatchApi
{
    public static partial class Program
    {
        public static JArray BatchCreate(string accessToken, string baseAddress, string spaceId)
        {
            JArray operations = new JArray();
            operations.Add(new JObject
            {
                ["method"] = "POST",
                ["href"] = $"{baseAddress}/api/space/{spaceId}/softtype/DesignPart/defaultIn",
                ["body"] = new JObject
                {
                    ["id"] = $"{Guid.NewGuid()}",
                    ["name"] = "Test DesignPart",
                    ["versionId"] = "A",
                    ["typeClass"] = new JObject
                    {
                        ["class"] = "TODO"
                    },
                    ["designDate"] = new JObject
                    {
                        ["date"] = "2018-06-01T00:00:00Z"
                    },
                    ["targetWeight"] = new JObject
                    {
                        ["value"] = 1234,
                        ["unit"] = "gram"
                    }
                }
            });
            operations.Add(new JObject
            {
                ["method"] = "POST",
                ["href"] = $"{baseAddress}/api/space/{spaceId}/softtype/DesignPart/defaultIn",
                ["body"] = new JObject
                {
                    ["id"] = $"{Guid.NewGuid()}",
                    ["name"] = "Test DesignPart",
                    ["versionId"] = "A",
                    ["typeClass"] = new JObject
                    {
                        ["class"] = "TODO"
                    },
                    ["designDate"] = new JObject
                    {
                        ["date"] = "2018-06-01T00:00:00Z"
                    },
                    ["targetWeight"] = new JObject
                    {
                        ["value"] = 1.2,
                        ["unit"] = "kilogram"
                    }
                }
            });

            return BatchCommit(accessToken, baseAddress, spaceId, operations);
        }
    }
}

The json body for this batch call will look something like this:

Batch Create Body

{[
  {
    "method": "POST",
    "href": "https://vm15/api/space/ic/softtype/DesignPart/defaultIn",
    "body": {
      "id": "05e76f14-9051-4485-a444-d41aa16ee1c5",
      "name": "Test DesignPart",
      "versionId": "A",
      "typeClass": {
        "class": "TODO"
      },
      "designDate": {
        "date": "2018-06-01T00:00:00Z"
      },
      "targetWeight": {
        "value": 1234,
        "unit": "gram"
      }
    }
  },
  {
    "method": "POST",
    "href": "https://vm15/api/space/ic/softtype/DesignPart/defaultIn",
    "body": {
      "id": "a328debe-7abe-49cc-9096-04fae858418a",
      "name": "Test DesignPart",
      "versionId": "A",
      "typeClass": {
        "class": "TODO"
      },
      "designDate": {
        "date": "2018-06-01T00:00:00Z"
      },
      "calculatedWeight": {
        "value": 1.2,
        "unit": "kilogram"
      }
    }
  }
]}

The response from the batch create will look something like this:

Batch Create Response

{[
  {
    "statusCode": 201,
    "body": {
      "href": "https://vm15/api/space/ic/softtype/DesignPart/09000000000000001201060000000400",
      "version": 1
    }
  },
  {
    "statusCode": 201,
    "body": {
      "href": "https://vm15/api/space/ic/softtype/DesignPart/0a000000000000001201060000000400",
      "version": 1
    }
  }
]}

Batch Maturity Promote

Using the response from the batch create we can retrieve the UoI-version and the UoI-OId needed to do a promote of the DesignPart's. Below is an promote example:

Batch Promote Code

using Newtonsoft.Json.Linq;
using System.Linq;

namespace Demo.BatchApi
{
    public static partial class Program
    {
        public static JArray BatchPromote(string accessToken, string baseAddress, string spaceId, JArray json)
        {
            JObject uoi1 = (JObject)json.First;
            JObject uoi2 = (JObject)json.Last;
            string oid1 = ((string)uoi1["body"]["href"]).Split('/').Last();
            string oid2 = ((string)uoi2["body"]["href"]).Split('/').Last();
            int uoiVersion1 = (int)uoi1["body"]["version"];
            int uoiVersion2 = (int)uoi2["body"]["version"];

            JArray operations = new JArray();
            operations.Add(new JObject
            {
                ["method"] = "PUT",
                ["href"] = $"{baseAddress}/api/space/{spaceId}/maturityAction/promote/{oid1}/commonReleaseProcessOEM/Review",
                ["headers"] = new JObject
                {
                    ["SAs-UOIVersion"] = uoiVersion1
                }
            });
            operations.Add(new JObject
            {
                ["method"] = "PUT",
                ["href"] = $"{baseAddress}/api/space/{spaceId}/maturityAction/promote/{oid2}/commonReleaseProcessOEM/Review",
                ["headers"] = new JObject
                {
                    ["SAs-UOIVersion"] = uoiVersion2
                }
            });

            return BatchCommit(accessToken, baseAddress, spaceId, operations);
        }
    }
}

The json body for the batch promote will look something like this:

Batch Promote Body

{[
  {
    "method": "PUT",
    "href": "https://vm15/api/space/ic/maturityAction/promote/09000000000000001201060000000400/commonReleaseProcessOEM/Review",
    "headers": {
      "SAs-UOIVersion": 1
    }
  },
  {
    "method": "PUT",
    "href": "https://vm15/api/space/ic/maturityAction/promote/0a000000000000001201060000000400/commonReleaseProcessOEM/Review",
    "headers": {
      "SAs-UOIVersion": 1
    }
  }
]}

The response from the batch promote will look something like this:

Batch Promote Response

{[
  {
    "statusCode": 204,
    "body": {
      "href": "https://vm15/api/space/ic/maturityAction/promote/09000000000000001201060000000400/commonReleaseProcessOEM/Review",
      "version": 2
    }
  },
  {
    "statusCode": 204,
    "body": {
      "href": "https://vm15/api/space/ic/maturityAction/promote/0a000000000000001201060000000400/commonReleaseProcessOEM/Review",
      "version": 2
    }
  }
]}

Batch SoftType Get

The response message from the batch create did not have all that was created and the associated links to the SoftType was not sent. To get the complete set of information around the created SoftTypes a batch get can be done, below is the example code:

Batch Get Code

using Newtonsoft.Json.Linq;
using System.Linq;

namespace Demo.BatchApi
{
    public static partial class Program
    {
        public static JArray BatchGet(string accessToken, string baseAddress, string spaceId, JArray json, string definitionId = "DesignPart", string schemaId = "defaultOut")
        {
            JObject uoi1 = (JObject)json.First;
            JObject uoi2 = (JObject)json.Last;
            string oid1 = ((string)uoi1["body"]["href"]).Split('/').Last();
            string oid2 = ((string)uoi2["body"]["href"]).Split('/').Last();

            JArray operations = new JArray();
            operations.Add(new JObject
            {
                ["method"] = "GET",
                ["href"] = $"{baseAddress}/api/space/{spaceId}/softtype/{definitionId}/{schemaId}/{oid1}",
            });
            operations.Add(new JObject
            {
                ["method"] = "GET",
                ["href"] = $"{baseAddress}/api/space/{spaceId}/softtype/{definitionId}/{schemaId}/{oid2}",
            });

            return BatchCommit(accessToken, baseAddress, spaceId, operations);
        }
    }
}

The json body for the batch get will contain everything a get response have for each SoftType.

Batch SoftType Edit

Having the complete set of information for the SoftTypes it is possible to do edit on them. However, when you have the complete set of information the normal method to edit with is PUT. But just for an example the code below does the edit with a PATCH instead:

Batch Edit Code

using Newtonsoft.Json.Linq;
using System.Linq;

namespace Demo.BatchApi
{
    public static partial class Program
    {
        public static JArray BatchEdit(string accessToken, string baseAddress, string spaceId, JArray json, string definitionId = "DesignPart", string schemaId = "defaultIn")
        {
            JObject uoi1 = (JObject)json.First;
            JObject uoi2 = (JObject)json.Last;
            string oid1 = ((string)uoi1["body"]["href"]).Split('/').Last();
            string oid2 = ((string)uoi2["body"]["href"]).Split('/').Last();
            int uoiVersion1 = (int)uoi1["body"]["version"];
            int uoiVersion2 = (int)uoi2["body"]["version"];
            JObject body1 = (JObject)uoi1["body"]["data"];
            JObject body2 = (JObject)uoi2["body"]["data"];

            body1["targetWeight"]["value"] = 2345;
            body2["targetWeight"]["value"] = 2.3;

            JArray operations = new JArray();
            operations.Add(new JObject
            {
                ["method"] = "PATCH",
                ["href"] = $"{baseAddress}/api/space/{spaceId}/softtype/{definitionId}/{schemaId}/{oid1}",
                ["body"] = body1,
                ["headers"] = new JObject
                {
                    ["SAs-UOIVersion"] = uoiVersion1
                }
            });
            operations.Add(new JObject
            {
                ["method"] = "PATCH",
                ["href"] = $"{baseAddress}/api/space/{spaceId}/softtype/{definitionId}/{schemaId}/{oid2}",
                ["body"] = body2,
                ["headers"] = new JObject
                {
                    ["SAs-UOIVersion"] = uoiVersion2
                }
            });

            return BatchCommit(accessToken, baseAddress, spaceId, operations);
        }
    }
}

The json body for the batch edit will look something like this:

Batch Edit Body

{[
  {
    "method": "PATCH",
    "href": "https://vm15/api/space/ic/softtype/DesignPart/defaultIn/25000000000000001201060000000400",
    "body": {
      "$version": 2,
      "$oid": "25000000000000001201060000000400",
      "$softType": "DesignPart",
      "masterOId": {
        "$oid": "25000000000000001201010000000400"
      },
      "softType": "DesignPart",
      "masterCreationDate": "2018-06-01T16:08:52Z",
      "masterCreatedBy": "admin@eurostep.com",
      "id": "6af0459f-130c-43dd-b6cd-24a7d8b243c3",
      "name": "Test DesignPart",
      "typeClass": {
        "start": "2018-06-01T16:08:52Z",
        "class": "TODO"
      },
      "versionOId": {
        "$oid": "25000000000000001201060000000400"
      },
      "versionCreationDate": "2018-06-01T16:08:52Z",
      "versionCreatedBy": "admin@eurostep.com",
      "versionId": "A",
      "designDate": {
        "start": "2018-06-01T16:08:52Z",
        "date": "2018-06-01T00:00:00Z"
      },
      "currentStateCommon": {
        "$oid": "02000000000000003300010000000400",
        "$softType": "LevelState",
        "id": "Review",
        "state": "InWork"
      },
      "currentStateDesign": {
        "$oid": "01000000000000003300010000000400",
        "$softType": "LevelState",
        "id": "InWork",
        "state": "InWork"
      },
      "targetWeight": {
        "value": 2345,
        "unit": "gram",
        "start": "2018-06-01T16:08:52Z"
      },
      "currentStateProduction": {
        "$oid": "01000000000000003300010000000400",
        "$softType": "LevelState",
        "id": "InWork",
        "state": "InWork"
      },
      "currentStateCostPrice": {
        "$oid": "01000000000000003300010000000400",
        "$softType": "LevelState",
        "id": "InWork",
        "state": "InWork"
      },
      "currentStateSparePart": {
        "$oid": "01000000000000003300010000000400",
        "$softType": "LevelState",
        "id": "InWork",
        "state": "InWork"
      }
    },
    "headers": {
      "SAs-UOIVersion": 2
    }
  },
  {
    "method": "PATCH",
    "href": "https://vm15/api/space/ic/softtype/DesignPart/defaultIn/26000000000000001201060000000400",
    "body": {
      "$version": 2,
      "$oid": "26000000000000001201060000000400",
      "$softType": "DesignPart",
      "masterOId": {
        "$oid": "26000000000000001201010000000400"
      },
      "softType": "DesignPart",
      "masterCreationDate": "2018-06-01T16:08:52Z",
      "masterCreatedBy": "admin@eurostep.com",
      "id": "4b6aebfe-bfb7-44e3-acac-0108e074fd82",
      "name": "Test DesignPart",
      "typeClass": {
        "start": "2018-06-01T16:08:52Z",
        "class": "TODO"
      },
      "versionOId": {
        "$oid": "26000000000000001201060000000400"
      },
      "versionCreationDate": "2018-06-01T16:08:52Z",
      "versionCreatedBy": "admin@eurostep.com",
      "versionId": "A",
      "designDate": {
        "start": "2018-06-01T16:08:52Z",
        "date": "2018-06-01T00:00:00Z"
      },
      "currentStateCommon": {
        "$oid": "02000000000000003300010000000400",
        "$softType": "LevelState",
        "id": "Review",
        "state": "InWork"
      },
      "currentStateDesign": {
        "$oid": "01000000000000003300010000000400",
        "$softType": "LevelState",
        "id": "InWork",
        "state": "InWork"
      },
      "targetWeight": {
        "value": 2.3,
        "unit": "kilogram",
        "start": "2018-06-01T16:08:52Z"
      },
      "currentStateProduction": {
        "$oid": "01000000000000003300010000000400",
        "$softType": "LevelState",
        "id": "InWork",
        "state": "InWork"
      },
      "currentStateCostPrice": {
        "$oid": "01000000000000003300010000000400",
        "$softType": "LevelState",
        "id": "InWork",
        "state": "InWork"
      },
      "currentStateSparePart": {
        "$oid": "01000000000000003300010000000400",
        "$softType": "LevelState",
        "id": "InWork",
        "state": "InWork"
      }
    },
    "headers": {
      "SAs-UOIVersion": 2
    }
  }
]}

The response from the batch edit will look something like this:

Batch Edit Response

{[
  {
    "statusCode": 204,
    "body": {
      "href": "https://vm15/api/space/ic/softtype/DesignPart/25000000000000001201010000000400",
      "version": 3
    }
  },
  {
    "statusCode": 204,
    "body": {
      "href": "https://vm15/api/space/ic/softtype/DesignPart/26000000000000001201010000000400",
      "version": 3
    }
  }
]}

Batch C-Sharp Example

The usage of above functions would look something like this:

Program

using Newtonsoft.Json.Linq;
using System;

namespace Demo.BatchApi
{
    public static partial class Program
    {
        public static void Main(string[] args)
        {
            string baseAddress = @"https://my.machine1.net";
            string userName = "MyEmail";
            string password = "MyPassword";
            string clientName = "ResourceOwnerClientId";
            string clientSecret = "CLIENTSECRET";
            string spaceId = "mytestspace";

            try
            {
                JObject token = Authenticate(baseAddress, userName, password, clientName, clientSecret);
                string accessToken = (string)token["access_token"];

                Console.WriteLine("Batch Create");
                JArray createResult = BatchCreate(accessToken, baseAddress, spaceId);
                Console.WriteLine(createResult);

                Console.WriteLine("Batch Promote");
                JArray promoteResult = BatchPromote(accessToken, baseAddress, spaceId, createResult);
                Console.WriteLine(promoteResult);

                Console.WriteLine("Batch Get");
                JArray getResult = BatchGet(accessToken, baseAddress, spaceId, createResult);
                Console.WriteLine(getResult);

                Console.WriteLine("Batch Edit");
                JArray editResult = BatchEdit(accessToken, baseAddress, spaceId, getResult);
                Console.WriteLine(editResult);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            Console.WriteLine("Press any key...");
            Console.ReadLine();
        }
    }
}

The examples above are collected in a project that can be downloaded.

Download Code

PowerShell Example


Caution

Sample code provided in here is for demonstration and educational purposes only which provides customers with programming information regarding the products and is not intended for use in a production environment. All production code should always follow development best practices. All sample code here is supplied "AS IS" without any warranties or support.

The batch function also works with PowerShell, in similar way as the C# example above. The provided example below has three functions:

  • GetAuthentication, a function to retrieve an access token
  • GetBody, a function that create an example of a batch create body
  • BatchCommit, the actual batch call

For other batch calls the GetBody function can be updated, the BatchCommit function will look the same for any batch call.

Download batch-create.ps1

function GetAuthentication($baseAddress)
{
    #OAuth 2.0 settings
    $username = "MyEmail"
    $password = "MyPassword"
    $scope = "All"
    $clientId = "ResourceOwnerClientId"
    $clientSecret = "CLIENTSECRET"
    $grantType = "password"
    $authUri = "$baseAddress/AuthorizationServer/sasweb/oauth/token"

    #Get bearerToken
    $basic = @{ 
        "Authorization" = ("Basic", [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(($clientId, $clientSecret -join ":"))) -join " ")
    }

    $authBody = @{ 
        "grant_type" = $grantType; 
        "username" = $username; 
        "password" = $password; 
        "scope" = $scope 
    }

    try{
        $response = Invoke-RestMethod -Method Post -Uri $authUri -ContentType "application/x-www-form-urlencoded" -Headers $basic -Body $authBody
        $bearerToken = $response.access_token
    }
    catch{
        $statusCode = $_.Exception.Response.StatusCode.value__
        $statusDescription = $_.Exception.Response.StatusDescription
        Write-Host "$($statusDescription)($($statusCode)); Uri: $($authUri); Response:$($_.Exception)"
        exit
    }
    return $bearerToken
}

function GetBody($baseAddress, $spaceId){
return 
'[{
     "method": "POST",
     "href": "'+$baseAddress+'/api/space/'+$spaceId+'/softtype/DesignPart/defaultIn",
     "body": {
         "id": "'+(New-Guid).Guid+'",
         "name": "Test DesignPart",
         "versionId": "A",
         "typeClass": {
         "class": "TODO"
         },
         "designDate": {
         "date": "2018-06-01T00:00:00Z"
         },
         "targetWeight": {
         "value": 1234,
         "unit": "gram"
         }
     }
     },
     {
     "method": "POST",
     "href": "'+$baseAddress+'/api/space/'+$spaceId+'/softtype/DesignPart/defaultIn",
     "body": {
         "id": "'+(New-Guid).Guid+'",
         "name": "Test DesignPart",
         "versionId": "A",
         "typeClass": {
         "class": "TODO"
         },
         "designDate": {
         "date": "2018-06-01T00:00:00Z"
         },
         "calculatedWeight": {
         "value": 1.2,
         "unit": "kilogram"
         }
     }
}]'
 }
 
function BatchCommit($baseAddress, $spaceId, $bearerToken, $body)
{
    try{
        $headers = @{"Authorization"="Bearer $bearerToken";}
        $requestUri = "$baseAddress/api/space/$spaceId/batch"
        $response = Invoke-RestMethod -Method Post -Uri $requestUri -Headers $headers -Body $body -ContentType "application/json"
    }
    catch{
        $statusCode = $_.Exception.Response.StatusCode.value__
        $statusDescription = $_.Exception.Response.StatusDescription
        Write-Host "$($statusDescription)($($statusCode)); Uri: $($requestUri); Response: $($_.Exception)"
    }
    return $response
}

$baseAddress = "https://my.machine1.net"
$spaceId = "mytestspace"
$bearerToken = GetAuthentication $baseAddress
$body = GetBody $baseAddress $spaceId
$response = BatchCommit $baseAddress $spaceId $bearerToken $body
Write-Host $response