{"_id":"56a0bda13697d80d002ac604","project":"54774d9af3736008009e9e0e","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"},"category":{"_id":"56b098a43a5b810d00745e3f","pages":["56b09b3b135ec20d00baf946"],"project":"54774d9af3736008009e9e0e","__v":1,"version":"56a0bd9e3697d80d002ac5e7","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-02-02T11:53:08.831Z","from_sync":false,"order":14,"slug":"sockets","title":"Sockets"},"user":"54774c47f3736008009e9e0c","__v":40,"parentDoc":null,"updates":["57a481c126785a0e00b69a64","57beba09fd5b9d0e00c55205"],"next":{"pages":[],"description":""},"createdAt":"2015-07-23T07:21:39.130Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"settings":"","results":{"codes":[]},"auth":"required","params":[],"url":""},"isReference":false,"order":1,"body":"[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Chapter Contents\"\n}\n[/block]\n1. [Overview](#overview)\n2. [What are Data Endpoints](#what-are-data-endpoints)\n3. [How to create Data Endpoints](#how-to-create-data-endpoints)\n   * [Creating a Data Endpoint](#section-creating-a-data-endpoint)\n   * [Creating a Data Endpoint with a reference schema field](#section-creating-a-data-endpoint-with-a-reference-schema-field)\n   * [Calling a Data Endpoint](#section-calling-a-data-endpoint)\n   * [Creating Data Objects from Data Endpoint](#section-creating-data-objects-from-data-endpoint)\n4. [Summary](#summary)\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Overview\"\n}\n[/block]\nIn the previous chapters, you have learned how to create, filter and order Data Objects. But what if you wanted to make a call that would filter and order the response, exclude some fields and return a specific numbers of Data Objects on page? \nOf course you can do that with Syncano but the call would have plenty of parameters and it would be at least cumbersome to use. And what if you wanted to have 10 of that kind of calls but with different parameters? Or 50? A nightmare to maintain!\n\nFortunately, we have a solution for that and it's called Data Endpoints. With this feature you can configure calls to Data Object endpoints and save them to be used later. \nThis way, you won't have to pass all the parameters every time you need to make a specific call. All you need to do, is make a call to specific Data Endpoint, that has all the parameters preconfigured. \n\nOk, let's see the Data Endpoints in action!\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"This chapter assumes that you already know how to create [Data Classes](doc:classes-overview) and [Data Objects](doc:data-objects) and you are familiar with [Data Object filtering and ordering](doc:data-objects-filtering)\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"What are Data Endpoints\"\n}\n[/block]\nAs mentioned above, Data Endpoints are custom calls to Data Objects endpoint that you can configure to suit your needs and save for later use. \nThese are the parameters that you can set up when creating a View:\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Parameter\",\n    \"h-1\": \"Description\",\n    \"0-0\": \"`order_by`\",\n    \"0-1\": \"You specify the ordering with this paramter. You will need to pass the field you want to order by as value. Default ordering is `ascending`.\",\n    \"1-0\": \"`page_size`\",\n    \"2-0\": \"`expand`\",\n    \"1-1\": \"Page size for the returned Data Objects. (You can read more about paging [here](http://docs.syncano.com/v0.1.1/docs/general-information#paging))\",\n    \"2-1\": \"Now this one is a bit tricky. Remember that you can create a reference or relation field inside a Data Object that will point it to a [different Data Object(s) from a target Data Class](doc:classes-data-field-types)? By passing a referenced/related Data Class name in the `expand` field, you'll be able to see whole referenced/related Data Object(s) in the configured View. More on this functionality in the examples below.\",\n    \"3-0\": \"`query`\",\n    \"3-1\": \"In this field you can specify a filtering method just as you would when using [Data Objects filtering.](http://docs.syncano.io/docs/data-objects-filtering-ordering#filtering-data-objects)\",\n    \"4-0\": \"`excluded_fields`\",\n    \"4-1\": \"Data Object fields that you would like to exclude from the response.\"\n  },\n  \"cols\": 2,\n  \"rows\": 5\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"How to create Data Endpoints\"\n}\n[/block]\n### Prerequisites\n\nBefore we create any Data Endpoints, we should have a Data Class ready. If we haven't, it's possible to create Data Class in step #2 when we will create our Data Endpoint. Also It would be good if it was also populated with some Data Objects. Lets say we have two Data Classes  \"inventory\" and \"warriors\" with the following schemas:\n- \"inventory\" Data Class:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/c625fde-Screen_Shot_2016-08-17_at_15.22.20.png\",\n        \"Screen Shot 2016-08-17 at 15.22.20.png\",\n        703,\n        142,\n        \"#343a58\"\n      ]\n    }\n  ]\n}\n[/block]\nInventory Data Class has two string fields, which will hold values of weapon and armor as strings.\n\n- \"warriors\" Data Class:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/fc14b3e-Screen_Shot_2016-08-17_at_15.24.09.png\",\n        \"Screen Shot 2016-08-17 at 15.24.09.png\",\n        705,\n        190,\n        \"#323e5e\"\n      ]\n    }\n  ]\n}\n[/block]\nWarriors Data Class has a name field. which will describe the warrior type, number field stating the number of warriors of this type and an inventory field, which references the \"Inventory\" Data Class.\n\n### Creating a Data Endpoint\n\nOk, let's create a Data Endpoint! \nOur goal here is:\n- The response should be sorted ascending by the `number` field\n- Inventory reference field should be expanded, so that it shows the referenced Data Objects\n- Response shouldn't consist of more than 4 Data Objects\n\nOur view will be called `troops` and will be based on the `warriors` Data Class. \nTo create such a view:\n1. Go to the Sockets page\n2. Click 'Add' button\n3. Fill and check fields in all steps as on the screenshots below\n4. Click 'Confirm' button\n5. Check your Summary Dialog\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/83f0413-Screen_Shot_2016-08-17_at_15.38.26.png\",\n        \"Screen Shot 2016-08-17 at 15.38.26.png\",\n        1920,\n        963,\n        \"#e5e6e9\"\n      ]\n    }\n  ]\n}\n[/block]\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/b78c5ca-Screen_Shot_2016-08-17_at_15.43.23.png\",\n        \"Screen Shot 2016-08-17 at 15.43.23.png\",\n        2560,\n        1349,\n        \"#1f5898\"\n      ]\n    }\n  ]\n}\n[/block]\nIf we created our data class earlier, the second step is skipped.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/4d74a11-Screen_Shot_2016-08-17_at_15.54.31.png\",\n        \"Screen Shot 2016-08-17 at 15.54.31.png\",\n        1037,\n        883,\n        \"#ececed\"\n      ]\n    }\n  ]\n}\n[/block]\nSummary Dialog with example code filled your custom data.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/24baac0-Screen_Shot_2016-08-17_at_16.09.22.png\",\n        \"Screen Shot 2016-08-17 at 16.09.22.png\",\n        1029,\n        863,\n        \"#d7d7d7\"\n      ]\n    }\n  ]\n}\n[/block]\n### Creating a Data Endpoint with a reference schema field\n\nNow, you definitely know how to create a Data Endpoint. But what if I were to tell you that you can get more than that? In a few seconds you are going to see how easily a connection between two (or more) objects can be made. \n\nWhen creating a data class, you have to remember to use a schema field called Reference. Let's assume that you have a data class called \"Authors\", with couple of data objects. At the same time you have another data class called \"Books\", with even more data objects. Now, whenever you would like to have some connection between Authors and Books - you can have it. What you should do is to click on the EXPAND field in a Data Endpoint. \n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/26bdec3-expand.png\",\n        \"expand.png\",\n        1838,\n        742,\n        \"#e9e9e9\"\n      ]\n    }\n  ]\n}\n[/block]\nNow, when you create a Data Object (Author) with a reference by ID to another Data Object (Book), it will be injected inside one another. \n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/375342e-id.png\",\n        \"id.png\",\n        1794,\n        838,\n        \"#1a4473\"\n      ]\n    }\n  ]\n}\n[/block]\nThis means you’ll have direct access to the referenced Data Object's properties. \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"id\\\": 7, \\n  \\\"created_at\\\": \\\"2016-08-09T06:29:04.474901Z\\\", \\n  \\\"updated_at\\\": \\\"2016-08-09T06:29:04.474924Z\\\", \\n  \\\"revision\\\": 1, \\n  \\\"owner\\\": null, \\n  \\\"owner_permissions\\\": \\\"full\\\", \\n  \\\"group\\\": null, \\n  \\\"group_permissions\\\": \\\"none\\\", \\n  \\\"other_permissions\\\": \\\"none\\\", \\n  \\\"channel\\\": null, \\n  \\\"channel_room\\\": null, \\n  \\\"string\\\": \\\"J. K. Rowling\\\",\\n  \\\"books_ref\\\": {\\n    \\\"id\\\": 1,                   \\n    \\\"created_at\\\": \\\"2016-08-08T09:47:05.266805Z\\\", \\n    \\\"updated_at\\\": \\\"2016-08-09T06:44:09.701958Z\\\", \\n    \\\"revision\\\": 2, \\n    \\\"owner\\\": null, \\n    \\\"owner_permissions\\\": \\\"full\\\", \\n    \\\"group\\\": null, \\n    \\\"group_permissions\\\": \\\"none\\\", \\n    \\\"other_permissions\\\": \\\"none\\\", \\n    \\\"channel\\\": null, \\n    \\\"channel_room\\\": null, \\n    \\\"rel\\\": null, \\n    \\\"ref\\\": null, \\n    \\\"string\\\": \\\"Harry Potter\\\",          \\n    \\\"links\\\": {\\n    \\\"self\\\": \\\"/v1.1/instances/restless-cloud-8272/classes/books/objects/1/\\\"\\n    }\\n \\t}, \\n  \\\"links\\\": {\\n  \\\"self\\\": \\\"/v1.1/instances/restless-cloud-8272/classes/authors/objects/7/\\\"\\n  }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n###  Calling a Data Endpoint\n\nNow when we have a Data Endpoint created, we can make a call to it. This is how such a call will look like:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X GET \\\\\\n-H \\\"X-API-KEY: API_KEY\\\" \\\\\\n\\\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/endpoints/data/troops/get/\\\"\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"[[Book pleaseForDataEndpoint::::at:::\\\"DATA-ENDPOINT-NAME\\\"] giveMeDataObjectsWithCompletion:^(NSArray * _Nullable objects, NSError * _Nullable error) {\\n   //Handle error\\n}];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"Book.please(forDataEndpoint: \\\"DATA_ENTPOIN_NAME\\\").giveMeDataObjects { (objects, error) in\\n    //Handle error\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nThe response will return the Data Objects that will meet the criteria we defined when creating the view (removed default properties for clarity):\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"next\\\": null,\\n    \\\"objects\\\": [\\n        {\\n            \\\"name\\\": \\\"sorcerers\\\",\\n            \\\"number\\\": 10,\\n            \\\"id\\\": 14,\\n            \\\"inventory\\\": {\\n                \\\"armor\\\": \\\"cloak\\\",\\n                \\\"id\\\": 11,\\n                \\\"weapon\\\": \\\"dagger\\\"\\n            }\\n        },\\n        {\\n            \\\"name\\\": \\\"palladins\\\",\\n            \\\"number\\\": 20,\\n            \\\"id\\\": 13,\\n            \\\"inventory\\\": {\\n                \\\"armor\\\": \\\"full plate armor\\\",\\n                \\\"id\\\": 15,\\n                \\\"weapon\\\": \\\"halberd\\\"\\n            }\\n        },\\n        {\\n            \\\"name\\\": \\\"goblins\\\",\\n            \\\"number\\\": 500,\\n            \\\"id\\\": 12,\\n            \\\"inventory\\\": {\\n                \\\"armor\\\": \\\"leather jacket\\\",\\n                \\\"id\\\": 10,\\n                \\\"weapon\\\": \\\"sword\\\"\\n            }\\n        },\\n        {\\n            \\\"name\\\": \\\"orcs\\\",\\n            \\\"number\\\": 1000,\\n            \\\"id\\\": 16,\\n            \\\"inventory\\\": {\\n                \\\"armor\\\": \\\"leather armor\\\",\\n                \\\"id\\\": 9,\\n                \\\"weapon\\\": \\\"axe\\\"\\n            }\\n        }\\n    ],\\n    \\\"prev\\\": null\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nWe've got exactly what we wanted. \nOur Data Endpoint returned warriors, that are sorted in an ascending order. \nThe inventory field that references the \"inventory\" Data Class, has it's fields expanded, so that you have access to all its fields. What is more, the view is limited to four results per page - exactly like we set it up.\n\n### Creating Data Objects from Data Endpoint \n\nThere is one extra Data Endpoint functionality. You can create new Data Object by simple Data Endpoint call with POST method, as in the code below:\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X POST \\\\\\n-H \\\"X-API-KEY: API_KEY\\\" \\\\\\n-H \\\"Content-Type: application/json\\\" \\\\\\n-d '{\\\"name\\\": \\\"golems\\\", \\\"number\\\": 300}' \\\\\\n\\\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/endpoints/data/troops/post/\\\"\",\n      \"language\": \"curl\",\n      \"name\": \"cURL\"\n    },\n    {\n      \"code\": \"var Syncano = require('syncano');\\nvar connection = Syncano({accountKey: 'ACCOUNT_KEY'});\\n\\nvar params = { name: 'DATAENDPOINT_NAME',\\n               instanceName: 'INSTANCE_NAME',\\n           \\t };\\n\\nvar data = { firstname: 'Peter',\\n             lastname: 'Parker',\\n             age: 28,\\n           };\\n\\nvar DataEndpoint = connection.DataEndpoint;\\n\\nDataEndpoint\\n  .please()\\n  .createDataObject(params, data)\\n  .then(function(res) { \\n      console.log(res);\\n  });\",\n      \"language\": \"javascript\",\n      \"name\": \"JavaScript\"\n    },\n    {\n      \"code\": \"@interface Book : SCDataObject\\[email protected] (nonatomic,retain) NSString *title;\\[email protected]\\n\\[email protected] Book\\n+ (NSString *)dataEndpointNameForAPI {\\n    return @\\\"DATA_ENDPOINT_NAME\\\";\\n}\\[email protected]\\n\\nBook *book = [Book new];\\nbook.title = @\\\"BOOK_TITLE\\\";\\n[book saveWithCompletionBlock:^(NSError * _Nullable error) {\\n\\n}];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"class Book: SCDataObject {\\n    var title:String?\\n\\n\\toverride class func dataEndpointNameForAPI() -> String? {\\n        return \\\"DATA_ENDPOINT_NAME\\\"\\n    }\\n}\\n\\nlet book:Book = Book()\\nbook.title = \\\"BOOK_TITLE\\\"\\nbook.saveWithCompletionBlock { (error) in\\n    //Handle error\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Summary\"\n}\n[/block]\nYou have just learned how to make Data Endpoints. \nIt will allow you to create really flexible and custom calls to Syncano and reduce the number of operations on the client side. \nThat's everything there is to know about working with Data Objects. \n\nNext on our reading list is learning about a feature allowing you to create and run scripts in the cloud, called [Script Endpoints](doc:endpoints-scripts).","excerpt":"In this chapter you will learn:\n- What are Data Endpoints\n- How to create Data Endpoints\n- How to expand the Data Endpoints","slug":"endpoints-data","type":"basic","title":"Data Endpoints"}

Data Endpoints

In this chapter you will learn: - What are Data Endpoints - How to create Data Endpoints - How to expand the Data Endpoints

[block:api-header] { "type": "basic", "title": "Chapter Contents" } [/block] 1. [Overview](#overview) 2. [What are Data Endpoints](#what-are-data-endpoints) 3. [How to create Data Endpoints](#how-to-create-data-endpoints) * [Creating a Data Endpoint](#section-creating-a-data-endpoint) * [Creating a Data Endpoint with a reference schema field](#section-creating-a-data-endpoint-with-a-reference-schema-field) * [Calling a Data Endpoint](#section-calling-a-data-endpoint) * [Creating Data Objects from Data Endpoint](#section-creating-data-objects-from-data-endpoint) 4. [Summary](#summary) [block:api-header] { "type": "basic", "title": "Overview" } [/block] In the previous chapters, you have learned how to create, filter and order Data Objects. But what if you wanted to make a call that would filter and order the response, exclude some fields and return a specific numbers of Data Objects on page? Of course you can do that with Syncano but the call would have plenty of parameters and it would be at least cumbersome to use. And what if you wanted to have 10 of that kind of calls but with different parameters? Or 50? A nightmare to maintain! Fortunately, we have a solution for that and it's called Data Endpoints. With this feature you can configure calls to Data Object endpoints and save them to be used later. This way, you won't have to pass all the parameters every time you need to make a specific call. All you need to do, is make a call to specific Data Endpoint, that has all the parameters preconfigured. Ok, let's see the Data Endpoints in action! [block:callout] { "type": "info", "body": "This chapter assumes that you already know how to create [Data Classes](doc:classes-overview) and [Data Objects](doc:data-objects) and you are familiar with [Data Object filtering and ordering](doc:data-objects-filtering)" } [/block] [block:api-header] { "type": "basic", "title": "What are Data Endpoints" } [/block] As mentioned above, Data Endpoints are custom calls to Data Objects endpoint that you can configure to suit your needs and save for later use. These are the parameters that you can set up when creating a View: [block:parameters] { "data": { "h-0": "Parameter", "h-1": "Description", "0-0": "`order_by`", "0-1": "You specify the ordering with this paramter. You will need to pass the field you want to order by as value. Default ordering is `ascending`.", "1-0": "`page_size`", "2-0": "`expand`", "1-1": "Page size for the returned Data Objects. (You can read more about paging [here](http://docs.syncano.com/v0.1.1/docs/general-information#paging))", "2-1": "Now this one is a bit tricky. Remember that you can create a reference or relation field inside a Data Object that will point it to a [different Data Object(s) from a target Data Class](doc:classes-data-field-types)? By passing a referenced/related Data Class name in the `expand` field, you'll be able to see whole referenced/related Data Object(s) in the configured View. More on this functionality in the examples below.", "3-0": "`query`", "3-1": "In this field you can specify a filtering method just as you would when using [Data Objects filtering.](http://docs.syncano.io/docs/data-objects-filtering-ordering#filtering-data-objects)", "4-0": "`excluded_fields`", "4-1": "Data Object fields that you would like to exclude from the response." }, "cols": 2, "rows": 5 } [/block] [block:api-header] { "type": "basic", "title": "How to create Data Endpoints" } [/block] ### Prerequisites Before we create any Data Endpoints, we should have a Data Class ready. If we haven't, it's possible to create Data Class in step #2 when we will create our Data Endpoint. Also It would be good if it was also populated with some Data Objects. Lets say we have two Data Classes "inventory" and "warriors" with the following schemas: - "inventory" Data Class: [block:image] { "images": [ { "image": [ "https://files.readme.io/c625fde-Screen_Shot_2016-08-17_at_15.22.20.png", "Screen Shot 2016-08-17 at 15.22.20.png", 703, 142, "#343a58" ] } ] } [/block] Inventory Data Class has two string fields, which will hold values of weapon and armor as strings. - "warriors" Data Class: [block:image] { "images": [ { "image": [ "https://files.readme.io/fc14b3e-Screen_Shot_2016-08-17_at_15.24.09.png", "Screen Shot 2016-08-17 at 15.24.09.png", 705, 190, "#323e5e" ] } ] } [/block] Warriors Data Class has a name field. which will describe the warrior type, number field stating the number of warriors of this type and an inventory field, which references the "Inventory" Data Class. ### Creating a Data Endpoint Ok, let's create a Data Endpoint! Our goal here is: - The response should be sorted ascending by the `number` field - Inventory reference field should be expanded, so that it shows the referenced Data Objects - Response shouldn't consist of more than 4 Data Objects Our view will be called `troops` and will be based on the `warriors` Data Class. To create such a view: 1. Go to the Sockets page 2. Click 'Add' button 3. Fill and check fields in all steps as on the screenshots below 4. Click 'Confirm' button 5. Check your Summary Dialog [block:image] { "images": [ { "image": [ "https://files.readme.io/83f0413-Screen_Shot_2016-08-17_at_15.38.26.png", "Screen Shot 2016-08-17 at 15.38.26.png", 1920, 963, "#e5e6e9" ] } ] } [/block] [block:image] { "images": [ { "image": [ "https://files.readme.io/b78c5ca-Screen_Shot_2016-08-17_at_15.43.23.png", "Screen Shot 2016-08-17 at 15.43.23.png", 2560, 1349, "#1f5898" ] } ] } [/block] If we created our data class earlier, the second step is skipped. [block:image] { "images": [ { "image": [ "https://files.readme.io/4d74a11-Screen_Shot_2016-08-17_at_15.54.31.png", "Screen Shot 2016-08-17 at 15.54.31.png", 1037, 883, "#ececed" ] } ] } [/block] Summary Dialog with example code filled your custom data. [block:image] { "images": [ { "image": [ "https://files.readme.io/24baac0-Screen_Shot_2016-08-17_at_16.09.22.png", "Screen Shot 2016-08-17 at 16.09.22.png", 1029, 863, "#d7d7d7" ] } ] } [/block] ### Creating a Data Endpoint with a reference schema field Now, you definitely know how to create a Data Endpoint. But what if I were to tell you that you can get more than that? In a few seconds you are going to see how easily a connection between two (or more) objects can be made. When creating a data class, you have to remember to use a schema field called Reference. Let's assume that you have a data class called "Authors", with couple of data objects. At the same time you have another data class called "Books", with even more data objects. Now, whenever you would like to have some connection between Authors and Books - you can have it. What you should do is to click on the EXPAND field in a Data Endpoint. [block:image] { "images": [ { "image": [ "https://files.readme.io/26bdec3-expand.png", "expand.png", 1838, 742, "#e9e9e9" ] } ] } [/block] Now, when you create a Data Object (Author) with a reference by ID to another Data Object (Book), it will be injected inside one another. [block:image] { "images": [ { "image": [ "https://files.readme.io/375342e-id.png", "id.png", 1794, 838, "#1a4473" ] } ] } [/block] This means you’ll have direct access to the referenced Data Object's properties. [block:code] { "codes": [ { "code": "{\n \"id\": 7, \n \"created_at\": \"2016-08-09T06:29:04.474901Z\", \n \"updated_at\": \"2016-08-09T06:29:04.474924Z\", \n \"revision\": 1, \n \"owner\": null, \n \"owner_permissions\": \"full\", \n \"group\": null, \n \"group_permissions\": \"none\", \n \"other_permissions\": \"none\", \n \"channel\": null, \n \"channel_room\": null, \n \"string\": \"J. K. Rowling\",\n \"books_ref\": {\n \"id\": 1, \n \"created_at\": \"2016-08-08T09:47:05.266805Z\", \n \"updated_at\": \"2016-08-09T06:44:09.701958Z\", \n \"revision\": 2, \n \"owner\": null, \n \"owner_permissions\": \"full\", \n \"group\": null, \n \"group_permissions\": \"none\", \n \"other_permissions\": \"none\", \n \"channel\": null, \n \"channel_room\": null, \n \"rel\": null, \n \"ref\": null, \n \"string\": \"Harry Potter\", \n \"links\": {\n \"self\": \"/v1.1/instances/restless-cloud-8272/classes/books/objects/1/\"\n }\n \t}, \n \"links\": {\n \"self\": \"/v1.1/instances/restless-cloud-8272/classes/authors/objects/7/\"\n }\n}", "language": "json" } ] } [/block] ### Calling a Data Endpoint Now when we have a Data Endpoint created, we can make a call to it. This is how such a call will look like: [block:code] { "codes": [ { "code": "curl -X GET \\\n-H \"X-API-KEY: API_KEY\" \\\n\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/endpoints/data/troops/get/\"", "language": "curl" }, { "code": "[[Book pleaseForDataEndpoint:@\"DATA-ENDPOINT-NAME\"] giveMeDataObjectsWithCompletion:^(NSArray * _Nullable objects, NSError * _Nullable error) {\n //Handle error\n}];", "language": "objectivec" }, { "code": "Book.please(forDataEndpoint: \"DATA_ENTPOIN_NAME\").giveMeDataObjects { (objects, error) in\n //Handle error\n}", "language": "swift" } ] } [/block] The response will return the Data Objects that will meet the criteria we defined when creating the view (removed default properties for clarity): [block:code] { "codes": [ { "code": "{\n \"next\": null,\n \"objects\": [\n {\n \"name\": \"sorcerers\",\n \"number\": 10,\n \"id\": 14,\n \"inventory\": {\n \"armor\": \"cloak\",\n \"id\": 11,\n \"weapon\": \"dagger\"\n }\n },\n {\n \"name\": \"palladins\",\n \"number\": 20,\n \"id\": 13,\n \"inventory\": {\n \"armor\": \"full plate armor\",\n \"id\": 15,\n \"weapon\": \"halberd\"\n }\n },\n {\n \"name\": \"goblins\",\n \"number\": 500,\n \"id\": 12,\n \"inventory\": {\n \"armor\": \"leather jacket\",\n \"id\": 10,\n \"weapon\": \"sword\"\n }\n },\n {\n \"name\": \"orcs\",\n \"number\": 1000,\n \"id\": 16,\n \"inventory\": {\n \"armor\": \"leather armor\",\n \"id\": 9,\n \"weapon\": \"axe\"\n }\n }\n ],\n \"prev\": null\n}", "language": "json" } ] } [/block] We've got exactly what we wanted. Our Data Endpoint returned warriors, that are sorted in an ascending order. The inventory field that references the "inventory" Data Class, has it's fields expanded, so that you have access to all its fields. What is more, the view is limited to four results per page - exactly like we set it up. ### Creating Data Objects from Data Endpoint There is one extra Data Endpoint functionality. You can create new Data Object by simple Data Endpoint call with POST method, as in the code below: [block:code] { "codes": [ { "code": "curl -X POST \\\n-H \"X-API-KEY: API_KEY\" \\\n-H \"Content-Type: application/json\" \\\n-d '{\"name\": \"golems\", \"number\": 300}' \\\n\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/endpoints/data/troops/post/\"", "language": "curl", "name": "cURL" }, { "code": "var Syncano = require('syncano');\nvar connection = Syncano({accountKey: 'ACCOUNT_KEY'});\n\nvar params = { name: 'DATAENDPOINT_NAME',\n instanceName: 'INSTANCE_NAME',\n \t };\n\nvar data = { firstname: 'Peter',\n lastname: 'Parker',\n age: 28,\n };\n\nvar DataEndpoint = connection.DataEndpoint;\n\nDataEndpoint\n .please()\n .createDataObject(params, data)\n .then(function(res) { \n console.log(res);\n });", "language": "javascript", "name": "JavaScript" }, { "code": "@interface Book : SCDataObject\[email protected] (nonatomic,retain) NSString *title;\[email protected]\n\[email protected] Book\n+ (NSString *)dataEndpointNameForAPI {\n return @\"DATA_ENDPOINT_NAME\";\n}\[email protected]\n\nBook *book = [Book new];\nbook.title = @\"BOOK_TITLE\";\n[book saveWithCompletionBlock:^(NSError * _Nullable error) {\n\n}];", "language": "objectivec" }, { "code": "class Book: SCDataObject {\n var title:String?\n\n\toverride class func dataEndpointNameForAPI() -> String? {\n return \"DATA_ENDPOINT_NAME\"\n }\n}\n\nlet book:Book = Book()\nbook.title = \"BOOK_TITLE\"\nbook.saveWithCompletionBlock { (error) in\n //Handle error\n}", "language": "swift" } ] } [/block] [block:api-header] { "type": "basic", "title": "Summary" } [/block] You have just learned how to make Data Endpoints. It will allow you to create really flexible and custom calls to Syncano and reduce the number of operations on the client side. That's everything there is to know about working with Data Objects. Next on our reading list is learning about a feature allowing you to create and run scripts in the cloud, called [Script Endpoints](doc:endpoints-scripts).