{"_id":"56a8c90fc48ee00d0092e1d1","parentDoc":null,"__v":31,"category":{"_id":"56a0bd9f3697d80d002ac5e9","__v":3,"project":"54774d9af3736008009e9e0e","version":"56a0bd9e3697d80d002ac5e7","pages":["56a0bda13697d80d002ac5ff","56a0bda13697d80d002ac600","56a0bda13697d80d002ac601","56a0bda13697d80d002ac602","56a0bda13697d80d002ac603","56a0bda13697d80d002ac604","56a0bda13697d80d002ac605","56a0bda13697d80d002ac606","56a0bda13697d80d002ac607","56a0bda13697d80d002ac608","56a0bda13697d80d002ac609","56a0bda13697d80d002ac60a","56a0bda13697d80d002ac60b","56a0bda13697d80d002ac60c","56a0bda13697d80d002ac60d","56a0bda13697d80d002ac60e","56a0bda13697d80d002ac60f","56a0bda13697d80d002ac610","56a0bda13697d80d002ac611","56a0bda13697d80d002ac612","56a0bda13697d80d002ac613","56a0bda13697d80d002ac614","56a5d7f7d222d20d00500d91","56a8c90fc48ee00d0092e1d1"],"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-02-05T14:34:09.364Z","from_sync":false,"order":17,"slug":"developer-manual","title":"Advanced Topics"},"project":"54774d9af3736008009e9e0e","user":"54774c47f3736008009e9e0c","version":{"_id":"56a0bd9e3697d80d002ac5e7","project":"54774d9af3736008009e9e0e","__v":20,"createdAt":"2016-01-21T11:14:38.131Z","releaseDate":"2016-01-21T11:14:38.131Z","categories":["56a0bd9f3697d80d002ac5e8","56a0bd9f3697d80d002ac5e9","56a0bd9f3697d80d002ac5ea","56a0bd9f3697d80d002ac5eb","56b098a43a5b810d00745e3f","56b098da8f7a4f0d0029dd10","56d5a8ecf612b80b00fb69cd","570989853ab43c0e0072b2d6","571006aa10300c0e007f6133","5735a52431a73b1700887ca0","5744b0529e045c0e00b7a7a2","5744b1d0b56d431700d8a4fb","5744b1fb55d65a0e00b436e1","5744b218f9c7411700ce560e","5744b220f9c7411700ce560f","5744b2259e045c0e00b7a7a7","5744b22cf8b79f0e00de6a2d","5744b23155d65a0e00b436e4","5744b242c758290e00fbc235","5744b2569e045c0e00b7a7a8","5756a3f2bb92962900dafe3d","57ee23e81e42900e0014a42f","581c822c98676e0f00d240ef"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"Sockets","version_clean":"1.1.0","version":"1.1"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-01-27T13:41:35.567Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"settings":"","results":{"codes":[]},"auth":"required","params":[],"url":""},"isReference":false,"order":3,"body":"[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Chapter Contents\"\n}\n[/block]\n1. [Introduction](#introduction)\n2. [Overview](#overview)\n3. [Creating a Batch Request](#creating-a-batch-request)\n4. [Summary](#summary)\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Introduction\"\n}\n[/block]\nThere might be cases where instead of sending single requests to Syncano, you'd like to group them into a one single, mighty request to rule them all. \n\nWe thought that you might like that and came up with **The Batch Requests**! \n\nThe concept behind batch requests is pretty simple. You make a request to the `batch` endpoint with a payload, where you specify a list of requests that you'd like to make. \nIn the response, you'll receive an array of objects containing the responses codes and content for the particular responses. \nWe'll get to the details below.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Overview\"\n}\n[/block]\nCreating a batch requests might differ when, depending on which library you use. \nThere are several rules though, that are common for all the libraries.\nInside a batch request, you can put all standard CRUD (create, read, update and delete) operations. \n\nWhen creating a batch request you can mix and match them freely. What is more -- the calls are not limited only to Data Objects. You can create a batch requests for any resource within a given instance. \nFor example, you can create a Data Object in one data class, delete a Channel and reset an Api Key. There are couple of limits that you should be aware of though:\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Limits\",\n  \"body\": \"- Number of requests can't exceed 50 per batch call\\n- Currently, it's not possible upload files using batch requests (when using Data Objects endpoint)\\n- Batch calls should be made within a scope of a single instance\"\n}\n[/block]\nSince the way of making a batch request differs for each library, the explanation is divided into categories:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"Endpoint for making batch requests:\\nhttps://api.syncano.io/v1/instances/INSTANCE_NAME/batch/\\n\\nAn array of requests should be passed as a request payload\\nEach request in the array should consist of:\\n\\n- \\\"method\\\" type: GET / POST / PATCH / PUT / DELETE\\n- \\\"path\\\": A location of the resource i.e.: \\\"/v1.1/instances/INSTANCE_NAME/classes/\\\"\\n- \\\"body\\\": JSON dictionary of additional parameters\\n\\nIn case of GET and DELETE requests the body property is ignored.\\nCredentials (API Key, Account Key, User Key) from the batch request are passed along to every sub request\",\n      \"name\": \"cURL\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"# The general syntax for making batch requests with python library is as follows:\\n\\nklass = instance.classes.get(name='some_class')\\n\\nObject.please.batch(\\n    klass.objects.as_batch().delete(id=652),\\n    klass.objects.as_batch().delete(id=653)\\n)\\n\\n\\\"\\\"\\\"\\nYou can mix up the create, delete and update requests but what is important to note is that the get() create() and get_or_create() requests won't work.\\n\\nYou can read more about the batch requests in the Syncano Python API Reference Library: http://syncano.github.io/syncano-python/refs/syncano.models.manager.html#module-syncano.models.manager\\n\\\"\\\"\\\"\\n\",\n      \"name\": \"python\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"var Syncano = require('syncano');\\n\\nvar connection = Syncano({ accountKey: 'ACCOUNT_KEY' });\\n\\n// Grab the manager from the connection\\n\\nvar Manager = connection.BatchManager({ instanceName: 'INSTANCE_NAME' });\\n\\n// Create an object for batching\\n\\nvar object = connection.DataObject({ className: 'CLASS_NAME', id: 'ID' });\\n\\n// Add object to batch\\n\\nManager.addSingleObject(object, 'delete');\\n\\n// Start the batch\\n\\nManager.batch().then(callback);\",\n      \"name\": \"JavaScript\",\n      \"language\": \"javascript\"\n    },\n    {\n      \"code\": \"SCBatch *batch = [SCBatch batch];\\n\\nBook *book = [Book new];\\nbook.title = :::at:::\\\"NEW BOOK\\\";\\n[batch addSaveRequestForDataObject:book error:nil];\\n\\n[batch sendWithCompletion:^(NSArray<SCBatchResponseItem *> * _Nullable items, NSError * _Nullable error) {\\n    \\n}];\\n\",\n      \"name\": \"\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"let book:Book = Book()\\nbook.title = \\\"New Book\\\"\\n\\nlet batch:SCBatch = SCBatch()\\nbatch.addSaveRequest(for: book, error: nil)\\nbatch.send { (response, error) in\\n    //Handle error\\n}\",\n      \"language\": \"swift\",\n      \"name\": \"Swift\"\n    },\n    {\n      \"code\": \"# Coming soon!\",\n      \"name\": \"Ruby\",\n      \"language\": \"ruby\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Creating a Batch Request\"\n}\n[/block]\nLet's try to use that information and design a batch request. \n\nWe'll create a batch request that will:\n- Add an API Key with an `allow_user_create` flag\n- Update a Data Object with an `id = 38`, from a data class named `class`\n- Delete a CodeBox with an `id = 2`\n\nThis is how this batch request should look like:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X POST \\\\\\n-H \\\"Content-type: application/json\\\" \\\\\\n-H \\\"X-API-KEY: ACCOUNT_KEY\\\" \\\\\\n-d '{\\n\\\"requests\\\":[\\n  {\\n     \\\"method\\\":\\\"POST\\\",\\n     \\\"path\\\":\\\"/v1.1/instances/INSTANCE_NAME/api_keys/\\\"\\n     \\\"body\\\": {\\\"allow_user_create\\\": true}\\n  },\\n  {\\n     \\\"method\\\":\\\"PATCH\\\",\\n     \\\"path\\\":\\\"/v1.1/instances/INSTANCE_NAME/classes/class/objects/38/\\\",\\n     \\\"body\\\": {\\\"string\\\": \\\"new\\\"}\\n  },\\n  {\\n     \\\"method\\\":\\\"DELETE\\\",\\n     \\\"path\\\":\\\"/v1.1/instances/INSTANCE_NAME/snippets/scripts/2/\\\"\\n  }\\n]\\n}' \\\\\\n\\\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/batch/\\\"\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"import syncano\\nfrom syncano.models.base import Instance\\n\\nconnection = syncano.connect(api_key='ACCOUNT_KEY')\\n\\ninstance = Instance(name='red-smoke-9323')\\nklass = instance.classes.get(name='class')\\n\\nObject.please.batch(\\n    instance.api_keys.as_batch().create(allow_user_create=True),\\n    klass.objects.as_batch().update(id=38, string='new'),\\n    instance.codeboxes.as_batch().delete(id=2)\\n)\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"var Syncano = require('syncano');\\n\\nvar connection = Syncano({ accountKey: 'ACCOUNT_KEY' });\\n\\nvar DataObject = connection.DataObject;\\nvar ApiKey = connection.ApiKey;\\nvar Script = connection.Script;\\n\\n// Grab the manager from the connection\\n\\nvar Manager = connection.BatchManager({ instanceName: 'INSTANCE_NAME' });\\n\\n// Add objects to batch\\n\\nManager.addObjects([\\n  { object: ApiKey({ allow_user_create: true }), action: 'create' },\\n  { object: DataObject({ id: 38, string: 'new', className: 'CLASS_NAME'}), action: 'update'  },\\n  { object: Script({ id: 2}), action: 'delete' }\\n]);\\n\\n// Start the batch\\n\\nManager.batch().then(callback);\",\n      \"language\": \"javascript\"\n    },\n    {\n      \"code\": \"// delete one object, update other\\nBatchBuilder batch = new BatchBuilder(syncano);\\nbatch.add(syncano.updateObject(book1));\\nbatch.add(syncano.deleteObject(book2));\\nResponse<List<BatchAnswer>> response = batch.send();\",\n      \"language\": \"java\",\n      \"name\": \"Android\"\n    },\n    {\n      \"code\": \"SCBatch *batch = [SCBatch batch];\\n\\nBook *book = [Book new];\\nbook.title = @\\\"NEW BOOK\\\";\\n[batch addSaveRequestForDataObject:book error:nil];\\n\\n[batch sendWithCompletion:^(NSArray<SCBatchResponseItem *> * _Nullable items, NSError * _Nullable error) {\\n    \\n}];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"let book:Book = Book()\\nbook.title = \\\"New Book\\\"\\n\\nlet batch:SCBatch = SCBatch()\\nbatch.addSaveRequest(for: book, error: nil)\\nbatch.send { (response, error) in\\n    //Handle error\\n}\",\n      \"language\": \"objectivec\",\n      \"name\": \"Swift\"\n    },\n    {\n      \"code\": \"# Coming soon!\",\n      \"language\": \"ruby\"\n    }\n  ]\n}\n[/block]\nAnd this is the response we received:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"[\\n    {\\n        \\\"code\\\": 201,\\n        \\\"content\\\": {\\n            \\\"allow_anonymous_read\\\": false,\\n            \\\"allow_user_create\\\": true,\\n            \\\"api_key\\\": \\\"e91c2410b9ecad7f00b48edbec11c6076cb2adbd\\\",\\n            \\\"created_at\\\": \\\"2016-01-28T14:20:01.451813Z\\\",\\n            \\\"description\\\": \\\"\\\",\\n            \\\"id\\\": 25831,\\n            \\\"ignore_acl\\\": false,\\n            \\\"links\\\": {\\n                \\\"reset_key\\\": \\\"/v1/instances/INSTANCE_NAME/api_keys/25831/reset_key/\\\",\\n                \\\"self\\\": \\\"/v1.1/instances/INSTANCE_NAME/api_keys/25831/\\\"\\n            }\\n        }\\n    },\\n    {\\n        \\\"code\\\": 200,\\n        \\\"content\\\": {\\n            \\\"channel\\\": null,\\n            \\\"channel_room\\\": null,\\n            \\\"created_at\\\": \\\"2016-01-27T13:09:25.621678Z\\\",\\n            \\\"group\\\": null,\\n            \\\"group_permissions\\\": \\\"none\\\",\\n            \\\"id\\\": 38,\\n            \\\"links\\\": {\\n                \\\"self\\\": \\\"/v1.1/instances/INSTANCE_NAME/classes/class/objects/38/\\\"\\n            },\\n            \\\"other_permissions\\\": \\\"none\\\",\\n            \\\"owner\\\": null,\\n            \\\"owner_permissions\\\": \\\"full\\\",\\n            \\\"revision\\\": 2,\\n            \\\"string\\\": \\\"new\\\",\\n            \\\"updated_at\\\": \\\"2016-01-28T14:20:01.481877Z\\\"\\n        }\\n    },\\n    {\\n        \\\"code\\\": 404,\\n        \\\"content\\\": {\\n            \\\"detail\\\": \\\"Not found.\\\"\\n        }\\n    }\\n]\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"[<ApiKey: 3378>, <RedSmoke9323ClassObject: 14>, {u'content': {u'detail': u'Not found.'}, u'code': 404}]\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"[\\n  { content:\\n     { created_at: '2016-09-18T09:20:49.851090Z',\\n       ignore_acl: false,\\n       links: [Object],\\n       allow_anonymous_read: false,\\n       description: '',\\n       api_key: '7c97cf585a67c71b02928de55a782e0b9270dd27',\\n       allow_group_create: false,\\n       id: 5544,\\n       allow_user_create: true },\\n    code: 201 },\\n  { content:\\n     { channel_room: null,\\n       group: null,\\n       links: [Object],\\n       string: 'new'\\n       group_permissions: 'none',\\n       created_at: '2016-09-15T16:39:53.287449Z',\\n       owner_permissions: 'full',\\n       updated_at: '2016-09-18T09:20:49.892457Z',\\n       id: 38,\\n       owner: null,\\n       other_permissions: 'none',\\n       channel: null,\\n       revision: 9 },\\n    code: 200 },\\n  { code: 204 }\\n]\",\n      \"language\": \"javascript\"\n    },\n    {\n      \"code\": \"List<BatchAnswer> answers = response.getData();\\nBook bookUdpated = answers.get(0).getDataAs(Book.class);\",\n      \"language\": \"java\",\n      \"name\": \"Android\"\n    },\n    {\n      \"code\": \"@interface SCBatchResponseItem : NSObject\\[email protected] (nonatomic,retain) NSNumber *code;\\[email protected] (nonatomic,retain) id content;\\[email protected] (nonatomic,retain) Class classToParse;\\[email protected]\\n  \\n#SDK will try to parse content objects. If parsing succeeds then parsed objects will be stored in `content` property\\n  \\n\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"class SCBatchResponseItem\\nvar code:NSNumber?\\nvar content:Any?\\nvar classToParse:class?\\n  \\n#SDK will try to parse content objects. If parsing succeeds then parsed objects will be stored in `content` property\",\n      \"language\": \"objectivec\",\n      \"name\": \"Swift\"\n    },\n    {\n      \"code\": \"# Coming soon!\",\n      \"language\": \"ruby\"\n    }\n  ]\n}\n[/block]\nAs you can see, the response has a form of an array, that contains three objects. \nThese objects correspond to the requests made in the batch call. \nThe first one, is the response to the first call (create API Key), the second to the second call (update Data Object) etc. \n\nEach of the objects, contains two properties:\n- `code`: it's the HTTP Status code of the response\n- `content`: response body\n\nIn the above example:\n- First call returned `201 CREATED` status code and content with info on created Api Key (with the `allow_user_create` set to true)\n- Second call returned `200 OK` status code and content with an updated a Data Object from the `class` Data Class\n- Third call returned `404 NOT FOUND` error code and content with the error message. This was expected, since we tried to delete a CodeBox that doesn't exist.\n\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Summary\"\n}\n[/block]\nThat's it! We hope making batch requests on Syncano will make your life easier!\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Pricing for Batch calls\",\n  \"body\": \"Pricing for the batch calls is the same as if the requests where sent individually. \\nE.g. if you send 50 API Calls to Download Objects - it will be counted as 50 API Calls against your limit. If you launch 50 CodeBoxes - it will also be counted as 50 CodeBox runs.\"\n}\n[/block]","excerpt":"In this chapter you'll learn:\n- What are batch requests\n- How to create a batch requests\n- How to execute a batch requests","slug":"request-batching","type":"basic","title":"Request Batching"}

Request Batching

In this chapter you'll learn: - What are batch requests - How to create a batch requests - How to execute a batch requests

[block:api-header] { "type": "basic", "title": "Chapter Contents" } [/block] 1. [Introduction](#introduction) 2. [Overview](#overview) 3. [Creating a Batch Request](#creating-a-batch-request) 4. [Summary](#summary) [block:api-header] { "type": "basic", "title": "Introduction" } [/block] There might be cases where instead of sending single requests to Syncano, you'd like to group them into a one single, mighty request to rule them all. We thought that you might like that and came up with **The Batch Requests**! The concept behind batch requests is pretty simple. You make a request to the `batch` endpoint with a payload, where you specify a list of requests that you'd like to make. In the response, you'll receive an array of objects containing the responses codes and content for the particular responses. We'll get to the details below. [block:api-header] { "type": "basic", "title": "Overview" } [/block] Creating a batch requests might differ when, depending on which library you use. There are several rules though, that are common for all the libraries. Inside a batch request, you can put all standard CRUD (create, read, update and delete) operations. When creating a batch request you can mix and match them freely. What is more -- the calls are not limited only to Data Objects. You can create a batch requests for any resource within a given instance. For example, you can create a Data Object in one data class, delete a Channel and reset an Api Key. There are couple of limits that you should be aware of though: [block:callout] { "type": "warning", "title": "Limits", "body": "- Number of requests can't exceed 50 per batch call\n- Currently, it's not possible upload files using batch requests (when using Data Objects endpoint)\n- Batch calls should be made within a scope of a single instance" } [/block] Since the way of making a batch request differs for each library, the explanation is divided into categories: [block:code] { "codes": [ { "code": "Endpoint for making batch requests:\nhttps://api.syncano.io/v1/instances/INSTANCE_NAME/batch/\n\nAn array of requests should be passed as a request payload\nEach request in the array should consist of:\n\n- \"method\" type: GET / POST / PATCH / PUT / DELETE\n- \"path\": A location of the resource i.e.: \"/v1.1/instances/INSTANCE_NAME/classes/\"\n- \"body\": JSON dictionary of additional parameters\n\nIn case of GET and DELETE requests the body property is ignored.\nCredentials (API Key, Account Key, User Key) from the batch request are passed along to every sub request", "name": "cURL", "language": "curl" }, { "code": "# The general syntax for making batch requests with python library is as follows:\n\nklass = instance.classes.get(name='some_class')\n\nObject.please.batch(\n klass.objects.as_batch().delete(id=652),\n klass.objects.as_batch().delete(id=653)\n)\n\n\"\"\"\nYou can mix up the create, delete and update requests but what is important to note is that the get() create() and get_or_create() requests won't work.\n\nYou can read more about the batch requests in the Syncano Python API Reference Library: http://syncano.github.io/syncano-python/refs/syncano.models.manager.html#module-syncano.models.manager\n\"\"\"\n", "name": "python", "language": "python" }, { "code": "var Syncano = require('syncano');\n\nvar connection = Syncano({ accountKey: 'ACCOUNT_KEY' });\n\n// Grab the manager from the connection\n\nvar Manager = connection.BatchManager({ instanceName: 'INSTANCE_NAME' });\n\n// Create an object for batching\n\nvar object = connection.DataObject({ className: 'CLASS_NAME', id: 'ID' });\n\n// Add object to batch\n\nManager.addSingleObject(object, 'delete');\n\n// Start the batch\n\nManager.batch().then(callback);", "name": "JavaScript", "language": "javascript" }, { "code": "SCBatch *batch = [SCBatch batch];\n\nBook *book = [Book new];\nbook.title = @\"NEW BOOK\";\n[batch addSaveRequestForDataObject:book error:nil];\n\n[batch sendWithCompletion:^(NSArray<SCBatchResponseItem *> * _Nullable items, NSError * _Nullable error) {\n \n}];\n", "name": "", "language": "objectivec" }, { "code": "let book:Book = Book()\nbook.title = \"New Book\"\n\nlet batch:SCBatch = SCBatch()\nbatch.addSaveRequest(for: book, error: nil)\nbatch.send { (response, error) in\n //Handle error\n}", "language": "swift", "name": "Swift" }, { "code": "# Coming soon!", "name": "Ruby", "language": "ruby" } ] } [/block] [block:api-header] { "type": "basic", "title": "Creating a Batch Request" } [/block] Let's try to use that information and design a batch request. We'll create a batch request that will: - Add an API Key with an `allow_user_create` flag - Update a Data Object with an `id = 38`, from a data class named `class` - Delete a CodeBox with an `id = 2` This is how this batch request should look like: [block:code] { "codes": [ { "code": "curl -X POST \\\n-H \"Content-type: application/json\" \\\n-H \"X-API-KEY: ACCOUNT_KEY\" \\\n-d '{\n\"requests\":[\n {\n \"method\":\"POST\",\n \"path\":\"/v1.1/instances/INSTANCE_NAME/api_keys/\"\n \"body\": {\"allow_user_create\": true}\n },\n {\n \"method\":\"PATCH\",\n \"path\":\"/v1.1/instances/INSTANCE_NAME/classes/class/objects/38/\",\n \"body\": {\"string\": \"new\"}\n },\n {\n \"method\":\"DELETE\",\n \"path\":\"/v1.1/instances/INSTANCE_NAME/snippets/scripts/2/\"\n }\n]\n}' \\\n\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/batch/\"", "language": "curl" }, { "code": "import syncano\nfrom syncano.models.base import Instance\n\nconnection = syncano.connect(api_key='ACCOUNT_KEY')\n\ninstance = Instance(name='red-smoke-9323')\nklass = instance.classes.get(name='class')\n\nObject.please.batch(\n instance.api_keys.as_batch().create(allow_user_create=True),\n klass.objects.as_batch().update(id=38, string='new'),\n instance.codeboxes.as_batch().delete(id=2)\n)", "language": "python" }, { "code": "var Syncano = require('syncano');\n\nvar connection = Syncano({ accountKey: 'ACCOUNT_KEY' });\n\nvar DataObject = connection.DataObject;\nvar ApiKey = connection.ApiKey;\nvar Script = connection.Script;\n\n// Grab the manager from the connection\n\nvar Manager = connection.BatchManager({ instanceName: 'INSTANCE_NAME' });\n\n// Add objects to batch\n\nManager.addObjects([\n { object: ApiKey({ allow_user_create: true }), action: 'create' },\n { object: DataObject({ id: 38, string: 'new', className: 'CLASS_NAME'}), action: 'update' },\n { object: Script({ id: 2}), action: 'delete' }\n]);\n\n// Start the batch\n\nManager.batch().then(callback);", "language": "javascript" }, { "code": "// delete one object, update other\nBatchBuilder batch = new BatchBuilder(syncano);\nbatch.add(syncano.updateObject(book1));\nbatch.add(syncano.deleteObject(book2));\nResponse<List<BatchAnswer>> response = batch.send();", "language": "java", "name": "Android" }, { "code": "SCBatch *batch = [SCBatch batch];\n\nBook *book = [Book new];\nbook.title = @\"NEW BOOK\";\n[batch addSaveRequestForDataObject:book error:nil];\n\n[batch sendWithCompletion:^(NSArray<SCBatchResponseItem *> * _Nullable items, NSError * _Nullable error) {\n \n}];", "language": "objectivec" }, { "code": "let book:Book = Book()\nbook.title = \"New Book\"\n\nlet batch:SCBatch = SCBatch()\nbatch.addSaveRequest(for: book, error: nil)\nbatch.send { (response, error) in\n //Handle error\n}", "language": "objectivec", "name": "Swift" }, { "code": "# Coming soon!", "language": "ruby" } ] } [/block] And this is the response we received: [block:code] { "codes": [ { "code": "[\n {\n \"code\": 201,\n \"content\": {\n \"allow_anonymous_read\": false,\n \"allow_user_create\": true,\n \"api_key\": \"e91c2410b9ecad7f00b48edbec11c6076cb2adbd\",\n \"created_at\": \"2016-01-28T14:20:01.451813Z\",\n \"description\": \"\",\n \"id\": 25831,\n \"ignore_acl\": false,\n \"links\": {\n \"reset_key\": \"/v1/instances/INSTANCE_NAME/api_keys/25831/reset_key/\",\n \"self\": \"/v1.1/instances/INSTANCE_NAME/api_keys/25831/\"\n }\n }\n },\n {\n \"code\": 200,\n \"content\": {\n \"channel\": null,\n \"channel_room\": null,\n \"created_at\": \"2016-01-27T13:09:25.621678Z\",\n \"group\": null,\n \"group_permissions\": \"none\",\n \"id\": 38,\n \"links\": {\n \"self\": \"/v1.1/instances/INSTANCE_NAME/classes/class/objects/38/\"\n },\n \"other_permissions\": \"none\",\n \"owner\": null,\n \"owner_permissions\": \"full\",\n \"revision\": 2,\n \"string\": \"new\",\n \"updated_at\": \"2016-01-28T14:20:01.481877Z\"\n }\n },\n {\n \"code\": 404,\n \"content\": {\n \"detail\": \"Not found.\"\n }\n }\n]", "language": "curl" }, { "code": "[<ApiKey: 3378>, <RedSmoke9323ClassObject: 14>, {u'content': {u'detail': u'Not found.'}, u'code': 404}]", "language": "python" }, { "code": "[\n { content:\n { created_at: '2016-09-18T09:20:49.851090Z',\n ignore_acl: false,\n links: [Object],\n allow_anonymous_read: false,\n description: '',\n api_key: '7c97cf585a67c71b02928de55a782e0b9270dd27',\n allow_group_create: false,\n id: 5544,\n allow_user_create: true },\n code: 201 },\n { content:\n { channel_room: null,\n group: null,\n links: [Object],\n string: 'new'\n group_permissions: 'none',\n created_at: '2016-09-15T16:39:53.287449Z',\n owner_permissions: 'full',\n updated_at: '2016-09-18T09:20:49.892457Z',\n id: 38,\n owner: null,\n other_permissions: 'none',\n channel: null,\n revision: 9 },\n code: 200 },\n { code: 204 }\n]", "language": "javascript" }, { "code": "List<BatchAnswer> answers = response.getData();\nBook bookUdpated = answers.get(0).getDataAs(Book.class);", "language": "java", "name": "Android" }, { "code": "@interface SCBatchResponseItem : NSObject\[email protected] (nonatomic,retain) NSNumber *code;\[email protected] (nonatomic,retain) id content;\[email protected] (nonatomic,retain) Class classToParse;\[email protected]\n \n#SDK will try to parse content objects. If parsing succeeds then parsed objects will be stored in `content` property\n \n", "language": "objectivec" }, { "code": "class SCBatchResponseItem\nvar code:NSNumber?\nvar content:Any?\nvar classToParse:class?\n \n#SDK will try to parse content objects. If parsing succeeds then parsed objects will be stored in `content` property", "language": "objectivec", "name": "Swift" }, { "code": "# Coming soon!", "language": "ruby" } ] } [/block] As you can see, the response has a form of an array, that contains three objects. These objects correspond to the requests made in the batch call. The first one, is the response to the first call (create API Key), the second to the second call (update Data Object) etc. Each of the objects, contains two properties: - `code`: it's the HTTP Status code of the response - `content`: response body In the above example: - First call returned `201 CREATED` status code and content with info on created Api Key (with the `allow_user_create` set to true) - Second call returned `200 OK` status code and content with an updated a Data Object from the `class` Data Class - Third call returned `404 NOT FOUND` error code and content with the error message. This was expected, since we tried to delete a CodeBox that doesn't exist. [block:api-header] { "type": "basic", "title": "Summary" } [/block] That's it! We hope making batch requests on Syncano will make your life easier! [block:callout] { "type": "info", "title": "Pricing for Batch calls", "body": "Pricing for the batch calls is the same as if the requests where sent individually. \nE.g. if you send 50 API Calls to Download Objects - it will be counted as 50 API Calls against your limit. If you launch 50 CodeBoxes - it will also be counted as 50 CodeBox runs." } [/block]